1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <drawinglayer/primitive2d/metafileprimitive2d.hxx> 32*cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx> 33*cdf0e10cSrcweir #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> 34*cdf0e10cSrcweir #include <basegfx/color/bcolor.hxx> 35*cdf0e10cSrcweir #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx> 36*cdf0e10cSrcweir #include <vcl/lineinfo.hxx> 37*cdf0e10cSrcweir #include <drawinglayer/attribute/lineattribute.hxx> 38*cdf0e10cSrcweir #include <drawinglayer/attribute/strokeattribute.hxx> 39*cdf0e10cSrcweir #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> 40*cdf0e10cSrcweir #include <vcl/metaact.hxx> 41*cdf0e10cSrcweir #include <drawinglayer/primitive2d/transformprimitive2d.hxx> 42*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrixtools.hxx> 43*cdf0e10cSrcweir #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> 44*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx> 45*cdf0e10cSrcweir #include <drawinglayer/primitive2d/discretebitmapprimitive2d.hxx> 46*cdf0e10cSrcweir #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> 47*cdf0e10cSrcweir #include <vcl/salbtype.hxx> 48*cdf0e10cSrcweir #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> 49*cdf0e10cSrcweir #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx> 50*cdf0e10cSrcweir #include <vcl/svapp.hxx> 51*cdf0e10cSrcweir #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx> 52*cdf0e10cSrcweir #include <drawinglayer/primitive2d/fillhatchprimitive2d.hxx> 53*cdf0e10cSrcweir #include <drawinglayer/primitive2d/maskprimitive2d.hxx> 54*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygonclipper.hxx> 55*cdf0e10cSrcweir #include <drawinglayer/primitive2d/invertprimitive2d.hxx> 56*cdf0e10cSrcweir #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> 57*cdf0e10cSrcweir #include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx> 58*cdf0e10cSrcweir #include <drawinglayer/primitive2d/wallpaperprimitive2d.hxx> 59*cdf0e10cSrcweir #include <drawinglayer/primitive2d/textprimitive2d.hxx> 60*cdf0e10cSrcweir #include <drawinglayer/primitive2d/textlayoutdevice.hxx> 61*cdf0e10cSrcweir #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx> 62*cdf0e10cSrcweir #include <i18npool/mslangid.hxx> 63*cdf0e10cSrcweir #include <drawinglayer/primitive2d/textlineprimitive2d.hxx> 64*cdf0e10cSrcweir #include <drawinglayer/primitive2d/textstrikeoutprimitive2d.hxx> 65*cdf0e10cSrcweir #include <drawinglayer/primitive2d/epsprimitive2d.hxx> 66*cdf0e10cSrcweir #include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx> 67*cdf0e10cSrcweir #include <numeric> 68*cdf0e10cSrcweir 69*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 70*cdf0e10cSrcweir 71*cdf0e10cSrcweir using namespace com::sun::star; 72*cdf0e10cSrcweir 73*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir namespace 76*cdf0e10cSrcweir { 77*cdf0e10cSrcweir /** helper class for graphic context 78*cdf0e10cSrcweir 79*cdf0e10cSrcweir This class allows to hold a complete status of classic 80*cdf0e10cSrcweir VCL OutputDevice stati. This data is needed for correct 81*cdf0e10cSrcweir interpretation of the MetaFile action flow. 82*cdf0e10cSrcweir */ 83*cdf0e10cSrcweir class PropertyHolder 84*cdf0e10cSrcweir { 85*cdf0e10cSrcweir private: 86*cdf0e10cSrcweir /// current transformation (aka MapMode) 87*cdf0e10cSrcweir basegfx::B2DHomMatrix maTransformation; 88*cdf0e10cSrcweir MapUnit maMapUnit; 89*cdf0e10cSrcweir 90*cdf0e10cSrcweir /// current colors 91*cdf0e10cSrcweir basegfx::BColor maLineColor; 92*cdf0e10cSrcweir basegfx::BColor maFillColor; 93*cdf0e10cSrcweir basegfx::BColor maTextColor; 94*cdf0e10cSrcweir basegfx::BColor maTextFillColor; 95*cdf0e10cSrcweir basegfx::BColor maTextLineColor; 96*cdf0e10cSrcweir basegfx::BColor maOverlineColor; 97*cdf0e10cSrcweir 98*cdf0e10cSrcweir /// clipping 99*cdf0e10cSrcweir basegfx::B2DPolyPolygon maClipPolyPoygon; 100*cdf0e10cSrcweir 101*cdf0e10cSrcweir /// font, etc. 102*cdf0e10cSrcweir Font maFont; 103*cdf0e10cSrcweir RasterOp maRasterOp; 104*cdf0e10cSrcweir sal_uInt32 mnLayoutMode; 105*cdf0e10cSrcweir LanguageType maLanguageType; 106*cdf0e10cSrcweir sal_uInt16 mnPushFlags; 107*cdf0e10cSrcweir 108*cdf0e10cSrcweir /// bitfield 109*cdf0e10cSrcweir /// contains all active markers 110*cdf0e10cSrcweir bool mbLineColor : 1; 111*cdf0e10cSrcweir bool mbFillColor : 1; 112*cdf0e10cSrcweir bool mbTextColor : 1; 113*cdf0e10cSrcweir bool mbTextFillColor : 1; 114*cdf0e10cSrcweir bool mbTextLineColor : 1; 115*cdf0e10cSrcweir bool mbOverlineColor : 1; 116*cdf0e10cSrcweir bool mbClipPolyPolygonActive : 1; 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir public: 119*cdf0e10cSrcweir PropertyHolder() 120*cdf0e10cSrcweir : maTransformation(), 121*cdf0e10cSrcweir maMapUnit(MAP_100TH_MM), 122*cdf0e10cSrcweir maLineColor(), 123*cdf0e10cSrcweir maFillColor(), 124*cdf0e10cSrcweir maTextColor(COL_BLACK), 125*cdf0e10cSrcweir maTextFillColor(), 126*cdf0e10cSrcweir maTextLineColor(), 127*cdf0e10cSrcweir maOverlineColor(), 128*cdf0e10cSrcweir maClipPolyPoygon(), 129*cdf0e10cSrcweir maFont(), 130*cdf0e10cSrcweir maRasterOp(ROP_OVERPAINT), 131*cdf0e10cSrcweir mnLayoutMode(0), 132*cdf0e10cSrcweir maLanguageType(0), 133*cdf0e10cSrcweir mnPushFlags(0), 134*cdf0e10cSrcweir mbLineColor(false), 135*cdf0e10cSrcweir mbFillColor(false), 136*cdf0e10cSrcweir mbTextColor(true), 137*cdf0e10cSrcweir mbTextFillColor(false), 138*cdf0e10cSrcweir mbTextLineColor(false), 139*cdf0e10cSrcweir mbOverlineColor(false), 140*cdf0e10cSrcweir mbClipPolyPolygonActive(false) 141*cdf0e10cSrcweir { 142*cdf0e10cSrcweir } 143*cdf0e10cSrcweir 144*cdf0e10cSrcweir ~PropertyHolder() 145*cdf0e10cSrcweir { 146*cdf0e10cSrcweir } 147*cdf0e10cSrcweir 148*cdf0e10cSrcweir /// read/write accesses 149*cdf0e10cSrcweir const basegfx::B2DHomMatrix& getTransformation() const { return maTransformation; } 150*cdf0e10cSrcweir void setTransformation(const basegfx::B2DHomMatrix& rNew) { if(rNew != maTransformation) maTransformation = rNew; } 151*cdf0e10cSrcweir 152*cdf0e10cSrcweir MapUnit getMapUnit() const { return maMapUnit; } 153*cdf0e10cSrcweir void setMapUnit(MapUnit eNew) { if(eNew != maMapUnit) maMapUnit = eNew; } 154*cdf0e10cSrcweir 155*cdf0e10cSrcweir const basegfx::BColor& getLineColor() const { return maLineColor; } 156*cdf0e10cSrcweir void setLineColor(const basegfx::BColor& rNew) { if(rNew != maLineColor) maLineColor = rNew; } 157*cdf0e10cSrcweir bool getLineColorActive() const { return mbLineColor; } 158*cdf0e10cSrcweir void setLineColorActive(bool bNew) { if(bNew != mbLineColor) mbLineColor = bNew; } 159*cdf0e10cSrcweir 160*cdf0e10cSrcweir const basegfx::BColor& getFillColor() const { return maFillColor; } 161*cdf0e10cSrcweir void setFillColor(const basegfx::BColor& rNew) { if(rNew != maFillColor) maFillColor = rNew; } 162*cdf0e10cSrcweir bool getFillColorActive() const { return mbFillColor; } 163*cdf0e10cSrcweir void setFillColorActive(bool bNew) { if(bNew != mbFillColor) mbFillColor = bNew; } 164*cdf0e10cSrcweir 165*cdf0e10cSrcweir const basegfx::BColor& getTextColor() const { return maTextColor; } 166*cdf0e10cSrcweir void setTextColor(const basegfx::BColor& rNew) { if(rNew != maTextColor) maTextColor = rNew; } 167*cdf0e10cSrcweir bool getTextColorActive() const { return mbTextColor; } 168*cdf0e10cSrcweir void setTextColorActive(bool bNew) { if(bNew != mbTextColor) mbTextColor = bNew; } 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir const basegfx::BColor& getTextFillColor() const { return maTextFillColor; } 171*cdf0e10cSrcweir void setTextFillColor(const basegfx::BColor& rNew) { if(rNew != maTextFillColor) maTextFillColor = rNew; } 172*cdf0e10cSrcweir bool getTextFillColorActive() const { return mbTextFillColor; } 173*cdf0e10cSrcweir void setTextFillColorActive(bool bNew) { if(bNew != mbTextFillColor) mbTextFillColor = bNew; } 174*cdf0e10cSrcweir 175*cdf0e10cSrcweir const basegfx::BColor& getTextLineColor() const { return maTextLineColor; } 176*cdf0e10cSrcweir void setTextLineColor(const basegfx::BColor& rNew) { if(rNew != maTextLineColor) maTextLineColor = rNew; } 177*cdf0e10cSrcweir bool getTextLineColorActive() const { return mbTextLineColor; } 178*cdf0e10cSrcweir void setTextLineColorActive(bool bNew) { if(bNew != mbTextLineColor) mbTextLineColor = bNew; } 179*cdf0e10cSrcweir 180*cdf0e10cSrcweir const basegfx::BColor& getOverlineColor() const { return maOverlineColor; } 181*cdf0e10cSrcweir void setOverlineColor(const basegfx::BColor& rNew) { if(rNew != maOverlineColor) maOverlineColor = rNew; } 182*cdf0e10cSrcweir bool getOverlineColorActive() const { return mbOverlineColor; } 183*cdf0e10cSrcweir void setOverlineColorActive(bool bNew) { if(bNew != mbOverlineColor) mbOverlineColor = bNew; } 184*cdf0e10cSrcweir 185*cdf0e10cSrcweir const basegfx::B2DPolyPolygon& getClipPolyPolygon() const { return maClipPolyPoygon; } 186*cdf0e10cSrcweir void setClipPolyPolygon(const basegfx::B2DPolyPolygon& rNew) { if(rNew != maClipPolyPoygon) maClipPolyPoygon = rNew; } 187*cdf0e10cSrcweir bool getClipPolyPolygonActive() const { return mbClipPolyPolygonActive; } 188*cdf0e10cSrcweir void setClipPolyPolygonActive(bool bNew) { if(bNew != mbClipPolyPolygonActive) mbClipPolyPolygonActive = bNew; } 189*cdf0e10cSrcweir 190*cdf0e10cSrcweir const Font& getFont() const { return maFont; } 191*cdf0e10cSrcweir void setFont(const Font& rFont) { if(rFont != maFont) maFont = rFont; } 192*cdf0e10cSrcweir 193*cdf0e10cSrcweir const RasterOp& getRasterOp() const { return maRasterOp; } 194*cdf0e10cSrcweir void setRasterOp(const RasterOp& rRasterOp) { if(rRasterOp != maRasterOp) maRasterOp = rRasterOp; } 195*cdf0e10cSrcweir bool isRasterOpInvert() const { return (ROP_XOR == maRasterOp || ROP_INVERT == maRasterOp); } 196*cdf0e10cSrcweir bool isRasterOpForceBlack() const { return ROP_0 == maRasterOp; } 197*cdf0e10cSrcweir bool isRasterOpActive() const { return isRasterOpInvert() || isRasterOpForceBlack(); } 198*cdf0e10cSrcweir 199*cdf0e10cSrcweir sal_uInt32 getLayoutMode() const { return mnLayoutMode; } 200*cdf0e10cSrcweir void setLayoutMode(sal_uInt32 nNew) { if(nNew != mnLayoutMode) mnLayoutMode = nNew; } 201*cdf0e10cSrcweir 202*cdf0e10cSrcweir LanguageType getLanguageType() const { return maLanguageType; } 203*cdf0e10cSrcweir void setLanguageType(LanguageType aNew) { if(aNew != maLanguageType) maLanguageType = aNew; } 204*cdf0e10cSrcweir 205*cdf0e10cSrcweir sal_uInt16 getPushFlags() const { return mnPushFlags; } 206*cdf0e10cSrcweir void setPushFlags(sal_uInt16 nNew) { if(nNew != mnPushFlags) mnPushFlags = nNew; } 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir bool getLineOrFillActive() const { return (mbLineColor || mbFillColor); } 209*cdf0e10cSrcweir }; 210*cdf0e10cSrcweir } // end of anonymous namespace 211*cdf0e10cSrcweir 212*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 213*cdf0e10cSrcweir 214*cdf0e10cSrcweir namespace 215*cdf0e10cSrcweir { 216*cdf0e10cSrcweir /** stack for properites 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir This class builds a stack based on the PropertyHolder 219*cdf0e10cSrcweir class. It encapsulates the pointer/new/delete usage to 220*cdf0e10cSrcweir make it safe and implements the push/pop as needed by a 221*cdf0e10cSrcweir VCL Metafile interpreter. The critical part here are the 222*cdf0e10cSrcweir flag values VCL OutputDevice uses here; not all stuff is 223*cdf0e10cSrcweir pushed and thus needs to be copied at pop. 224*cdf0e10cSrcweir */ 225*cdf0e10cSrcweir class PropertyHolders 226*cdf0e10cSrcweir { 227*cdf0e10cSrcweir private: 228*cdf0e10cSrcweir std::vector< PropertyHolder* > maPropertyHolders; 229*cdf0e10cSrcweir 230*cdf0e10cSrcweir public: 231*cdf0e10cSrcweir PropertyHolders() 232*cdf0e10cSrcweir { 233*cdf0e10cSrcweir maPropertyHolders.push_back(new PropertyHolder()); 234*cdf0e10cSrcweir } 235*cdf0e10cSrcweir 236*cdf0e10cSrcweir sal_uInt32 size() 237*cdf0e10cSrcweir { 238*cdf0e10cSrcweir return maPropertyHolders.size(); 239*cdf0e10cSrcweir } 240*cdf0e10cSrcweir 241*cdf0e10cSrcweir void PushDefault() 242*cdf0e10cSrcweir { 243*cdf0e10cSrcweir PropertyHolder* pNew = new PropertyHolder(); 244*cdf0e10cSrcweir maPropertyHolders.push_back(pNew); 245*cdf0e10cSrcweir } 246*cdf0e10cSrcweir 247*cdf0e10cSrcweir void Push(sal_uInt16 nPushFlags) 248*cdf0e10cSrcweir { 249*cdf0e10cSrcweir if(nPushFlags) 250*cdf0e10cSrcweir { 251*cdf0e10cSrcweir OSL_ENSURE(maPropertyHolders.size(), "PropertyHolders: PUSH with no property holders (!)"); 252*cdf0e10cSrcweir if ( !maPropertyHolders.empty() ) 253*cdf0e10cSrcweir { 254*cdf0e10cSrcweir PropertyHolder* pNew = new PropertyHolder(*maPropertyHolders.back()); 255*cdf0e10cSrcweir pNew->setPushFlags(nPushFlags); 256*cdf0e10cSrcweir maPropertyHolders.push_back(pNew); 257*cdf0e10cSrcweir } 258*cdf0e10cSrcweir } 259*cdf0e10cSrcweir } 260*cdf0e10cSrcweir 261*cdf0e10cSrcweir void Pop() 262*cdf0e10cSrcweir { 263*cdf0e10cSrcweir OSL_ENSURE(maPropertyHolders.size(), "PropertyHolders: POP with no property holders (!)"); 264*cdf0e10cSrcweir const sal_uInt32 nSize(maPropertyHolders.size()); 265*cdf0e10cSrcweir 266*cdf0e10cSrcweir if(nSize) 267*cdf0e10cSrcweir { 268*cdf0e10cSrcweir const PropertyHolder* pTip = maPropertyHolders.back(); 269*cdf0e10cSrcweir const sal_uInt16 nPushFlags(pTip->getPushFlags()); 270*cdf0e10cSrcweir 271*cdf0e10cSrcweir if(nPushFlags) 272*cdf0e10cSrcweir { 273*cdf0e10cSrcweir if(nSize > 1) 274*cdf0e10cSrcweir { 275*cdf0e10cSrcweir // copy back content for all non-set flags 276*cdf0e10cSrcweir PropertyHolder* pLast = maPropertyHolders[nSize - 2]; 277*cdf0e10cSrcweir 278*cdf0e10cSrcweir if(PUSH_ALL != nPushFlags) 279*cdf0e10cSrcweir { 280*cdf0e10cSrcweir if(!(nPushFlags & PUSH_LINECOLOR )) 281*cdf0e10cSrcweir { 282*cdf0e10cSrcweir pLast->setLineColor(pTip->getLineColor()); 283*cdf0e10cSrcweir pLast->setLineColorActive(pTip->getLineColorActive()); 284*cdf0e10cSrcweir } 285*cdf0e10cSrcweir if(!(nPushFlags & PUSH_FILLCOLOR )) 286*cdf0e10cSrcweir { 287*cdf0e10cSrcweir pLast->setFillColor(pTip->getFillColor()); 288*cdf0e10cSrcweir pLast->setFillColorActive(pTip->getFillColorActive()); 289*cdf0e10cSrcweir } 290*cdf0e10cSrcweir if(!(nPushFlags & PUSH_FONT )) 291*cdf0e10cSrcweir { 292*cdf0e10cSrcweir pLast->setFont(pTip->getFont()); 293*cdf0e10cSrcweir } 294*cdf0e10cSrcweir if(!(nPushFlags & PUSH_TEXTCOLOR )) 295*cdf0e10cSrcweir { 296*cdf0e10cSrcweir pLast->setTextColor(pTip->getTextColor()); 297*cdf0e10cSrcweir pLast->setTextColorActive(pTip->getTextColorActive()); 298*cdf0e10cSrcweir } 299*cdf0e10cSrcweir if(!(nPushFlags & PUSH_MAPMODE )) 300*cdf0e10cSrcweir { 301*cdf0e10cSrcweir pLast->setTransformation(pTip->getTransformation()); 302*cdf0e10cSrcweir pLast->setMapUnit(pTip->getMapUnit()); 303*cdf0e10cSrcweir } 304*cdf0e10cSrcweir if(!(nPushFlags & PUSH_CLIPREGION )) 305*cdf0e10cSrcweir { 306*cdf0e10cSrcweir pLast->setClipPolyPolygon(pTip->getClipPolyPolygon()); 307*cdf0e10cSrcweir pLast->setClipPolyPolygonActive(pTip->getClipPolyPolygonActive()); 308*cdf0e10cSrcweir } 309*cdf0e10cSrcweir if(!(nPushFlags & PUSH_RASTEROP )) 310*cdf0e10cSrcweir { 311*cdf0e10cSrcweir pLast->setRasterOp(pTip->getRasterOp()); 312*cdf0e10cSrcweir } 313*cdf0e10cSrcweir if(!(nPushFlags & PUSH_TEXTFILLCOLOR )) 314*cdf0e10cSrcweir { 315*cdf0e10cSrcweir pLast->setTextFillColor(pTip->getTextFillColor()); 316*cdf0e10cSrcweir pLast->setTextFillColorActive(pTip->getTextFillColorActive()); 317*cdf0e10cSrcweir } 318*cdf0e10cSrcweir if(!(nPushFlags & PUSH_TEXTALIGN )) 319*cdf0e10cSrcweir { 320*cdf0e10cSrcweir if(pLast->getFont().GetAlign() != pTip->getFont().GetAlign()) 321*cdf0e10cSrcweir { 322*cdf0e10cSrcweir Font aFont(pLast->getFont()); 323*cdf0e10cSrcweir aFont.SetAlign(pTip->getFont().GetAlign()); 324*cdf0e10cSrcweir pLast->setFont(aFont); 325*cdf0e10cSrcweir } 326*cdf0e10cSrcweir } 327*cdf0e10cSrcweir if(!(nPushFlags & PUSH_REFPOINT )) 328*cdf0e10cSrcweir { 329*cdf0e10cSrcweir // not supported 330*cdf0e10cSrcweir } 331*cdf0e10cSrcweir if(!(nPushFlags & PUSH_TEXTLINECOLOR )) 332*cdf0e10cSrcweir { 333*cdf0e10cSrcweir pLast->setTextLineColor(pTip->getTextLineColor()); 334*cdf0e10cSrcweir pLast->setTextLineColorActive(pTip->getTextLineColorActive()); 335*cdf0e10cSrcweir } 336*cdf0e10cSrcweir if(!(nPushFlags & PUSH_TEXTLAYOUTMODE )) 337*cdf0e10cSrcweir { 338*cdf0e10cSrcweir pLast->setLayoutMode(pTip->getLayoutMode()); 339*cdf0e10cSrcweir } 340*cdf0e10cSrcweir if(!(nPushFlags & PUSH_TEXTLANGUAGE )) 341*cdf0e10cSrcweir { 342*cdf0e10cSrcweir pLast->setLanguageType(pTip->getLanguageType()); 343*cdf0e10cSrcweir } 344*cdf0e10cSrcweir if(!(nPushFlags & PUSH_OVERLINECOLOR )) 345*cdf0e10cSrcweir { 346*cdf0e10cSrcweir pLast->setOverlineColor(pTip->getOverlineColor()); 347*cdf0e10cSrcweir pLast->setOverlineColorActive(pTip->getOverlineColorActive()); 348*cdf0e10cSrcweir } 349*cdf0e10cSrcweir } 350*cdf0e10cSrcweir } 351*cdf0e10cSrcweir } 352*cdf0e10cSrcweir 353*cdf0e10cSrcweir // execute the pop 354*cdf0e10cSrcweir delete maPropertyHolders.back(); 355*cdf0e10cSrcweir maPropertyHolders.pop_back(); 356*cdf0e10cSrcweir } 357*cdf0e10cSrcweir } 358*cdf0e10cSrcweir 359*cdf0e10cSrcweir PropertyHolder& Current() 360*cdf0e10cSrcweir { 361*cdf0e10cSrcweir static PropertyHolder aDummy; 362*cdf0e10cSrcweir OSL_ENSURE(maPropertyHolders.size(), "PropertyHolders: CURRENT with no property holders (!)"); 363*cdf0e10cSrcweir return maPropertyHolders.empty() ? aDummy : *maPropertyHolders.back(); 364*cdf0e10cSrcweir } 365*cdf0e10cSrcweir 366*cdf0e10cSrcweir ~PropertyHolders() 367*cdf0e10cSrcweir { 368*cdf0e10cSrcweir while(maPropertyHolders.size()) 369*cdf0e10cSrcweir { 370*cdf0e10cSrcweir delete maPropertyHolders.back(); 371*cdf0e10cSrcweir maPropertyHolders.pop_back(); 372*cdf0e10cSrcweir } 373*cdf0e10cSrcweir } 374*cdf0e10cSrcweir }; 375*cdf0e10cSrcweir } // end of anonymous namespace 376*cdf0e10cSrcweir 377*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 378*cdf0e10cSrcweir 379*cdf0e10cSrcweir namespace 380*cdf0e10cSrcweir { 381*cdf0e10cSrcweir /** helper to convert a Region to a B2DPolyPolygon 382*cdf0e10cSrcweir when it does not yet contain one. In the future 383*cdf0e10cSrcweir this may be expanded to merge the polygons created 384*cdf0e10cSrcweir from rectangles or use a special algo to directly turn 385*cdf0e10cSrcweir the spans of regions to a single, already merged 386*cdf0e10cSrcweir PolyPolygon. 387*cdf0e10cSrcweir */ 388*cdf0e10cSrcweir basegfx::B2DPolyPolygon getB2DPolyPolygonFromRegion(const Region& rRegion) 389*cdf0e10cSrcweir { 390*cdf0e10cSrcweir basegfx::B2DPolyPolygon aRetval; 391*cdf0e10cSrcweir 392*cdf0e10cSrcweir if(!rRegion.IsEmpty()) 393*cdf0e10cSrcweir { 394*cdf0e10cSrcweir Region aRegion(rRegion); 395*cdf0e10cSrcweir aRetval = aRegion.GetB2DPolyPolygon(); 396*cdf0e10cSrcweir 397*cdf0e10cSrcweir if(!aRetval.count()) 398*cdf0e10cSrcweir { 399*cdf0e10cSrcweir RegionHandle aRegionHandle(aRegion.BeginEnumRects()); 400*cdf0e10cSrcweir Rectangle aRegionRectangle; 401*cdf0e10cSrcweir 402*cdf0e10cSrcweir while(aRegion.GetEnumRects(aRegionHandle, aRegionRectangle)) 403*cdf0e10cSrcweir { 404*cdf0e10cSrcweir if(!aRegionRectangle.IsEmpty()) 405*cdf0e10cSrcweir { 406*cdf0e10cSrcweir const basegfx::B2DRange aRegionRange( 407*cdf0e10cSrcweir aRegionRectangle.Left(), aRegionRectangle.Top(), 408*cdf0e10cSrcweir aRegionRectangle.Right(), aRegionRectangle.Bottom()); 409*cdf0e10cSrcweir aRetval.append(basegfx::tools::createPolygonFromRect(aRegionRange)); 410*cdf0e10cSrcweir } 411*cdf0e10cSrcweir } 412*cdf0e10cSrcweir 413*cdf0e10cSrcweir aRegion.EndEnumRects(aRegionHandle); 414*cdf0e10cSrcweir } 415*cdf0e10cSrcweir } 416*cdf0e10cSrcweir 417*cdf0e10cSrcweir return aRetval; 418*cdf0e10cSrcweir } 419*cdf0e10cSrcweir } // end of anonymous namespace 420*cdf0e10cSrcweir 421*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 422*cdf0e10cSrcweir 423*cdf0e10cSrcweir namespace 424*cdf0e10cSrcweir { 425*cdf0e10cSrcweir /** Helper class to buffer and hold a Primive target vector. It 426*cdf0e10cSrcweir encapsulates the new/delete functionality and aloows to work 427*cdf0e10cSrcweir on pointers of the implementation classes. All data will 428*cdf0e10cSrcweir be converted to uno sequences of uno references when accessing the 429*cdf0e10cSrcweir data. 430*cdf0e10cSrcweir */ 431*cdf0e10cSrcweir class TargetHolder 432*cdf0e10cSrcweir { 433*cdf0e10cSrcweir private: 434*cdf0e10cSrcweir std::vector< drawinglayer::primitive2d::BasePrimitive2D* > aTargets; 435*cdf0e10cSrcweir 436*cdf0e10cSrcweir public: 437*cdf0e10cSrcweir TargetHolder() 438*cdf0e10cSrcweir : aTargets() 439*cdf0e10cSrcweir { 440*cdf0e10cSrcweir } 441*cdf0e10cSrcweir 442*cdf0e10cSrcweir ~TargetHolder() 443*cdf0e10cSrcweir { 444*cdf0e10cSrcweir const sal_uInt32 nCount(aTargets.size()); 445*cdf0e10cSrcweir 446*cdf0e10cSrcweir for(sal_uInt32 a(0); a < nCount; a++) 447*cdf0e10cSrcweir { 448*cdf0e10cSrcweir delete aTargets[a]; 449*cdf0e10cSrcweir } 450*cdf0e10cSrcweir } 451*cdf0e10cSrcweir 452*cdf0e10cSrcweir sal_uInt32 size() 453*cdf0e10cSrcweir { 454*cdf0e10cSrcweir return aTargets.size(); 455*cdf0e10cSrcweir } 456*cdf0e10cSrcweir 457*cdf0e10cSrcweir void append(drawinglayer::primitive2d::BasePrimitive2D* pCandidate) 458*cdf0e10cSrcweir { 459*cdf0e10cSrcweir if(pCandidate) 460*cdf0e10cSrcweir { 461*cdf0e10cSrcweir aTargets.push_back(pCandidate); 462*cdf0e10cSrcweir } 463*cdf0e10cSrcweir } 464*cdf0e10cSrcweir 465*cdf0e10cSrcweir drawinglayer::primitive2d::Primitive2DSequence getPrimitive2DSequence(const PropertyHolder& rPropertyHolder) 466*cdf0e10cSrcweir { 467*cdf0e10cSrcweir const sal_uInt32 nCount(aTargets.size()); 468*cdf0e10cSrcweir drawinglayer::primitive2d::Primitive2DSequence xRetval(nCount); 469*cdf0e10cSrcweir 470*cdf0e10cSrcweir for(sal_uInt32 a(0); a < nCount; a++) 471*cdf0e10cSrcweir { 472*cdf0e10cSrcweir xRetval[a] = aTargets[a]; 473*cdf0e10cSrcweir } 474*cdf0e10cSrcweir 475*cdf0e10cSrcweir // All Targets were pointers, but do not need to be deleted since they 476*cdf0e10cSrcweir // were converted to UNO API references now, so they stay as long as 477*cdf0e10cSrcweir // referenced. Do NOT delete the C++ implementation classes here, but clear 478*cdf0e10cSrcweir // the buffer to not delete them in the destructor. 479*cdf0e10cSrcweir aTargets.clear(); 480*cdf0e10cSrcweir 481*cdf0e10cSrcweir if(xRetval.hasElements() && rPropertyHolder.getClipPolyPolygonActive()) 482*cdf0e10cSrcweir { 483*cdf0e10cSrcweir const basegfx::B2DPolyPolygon& rClipPolyPolygon = rPropertyHolder.getClipPolyPolygon(); 484*cdf0e10cSrcweir 485*cdf0e10cSrcweir if(rClipPolyPolygon.count()) 486*cdf0e10cSrcweir { 487*cdf0e10cSrcweir const drawinglayer::primitive2d::Primitive2DReference xMask( 488*cdf0e10cSrcweir new drawinglayer::primitive2d::MaskPrimitive2D( 489*cdf0e10cSrcweir rClipPolyPolygon, 490*cdf0e10cSrcweir xRetval)); 491*cdf0e10cSrcweir 492*cdf0e10cSrcweir xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xMask, 1); 493*cdf0e10cSrcweir } 494*cdf0e10cSrcweir } 495*cdf0e10cSrcweir 496*cdf0e10cSrcweir return xRetval; 497*cdf0e10cSrcweir } 498*cdf0e10cSrcweir }; 499*cdf0e10cSrcweir } // end of anonymous namespace 500*cdf0e10cSrcweir 501*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 502*cdf0e10cSrcweir 503*cdf0e10cSrcweir namespace 504*cdf0e10cSrcweir { 505*cdf0e10cSrcweir /** Helper class which builds a stack on the TargetHolder class */ 506*cdf0e10cSrcweir class TargetHolders 507*cdf0e10cSrcweir { 508*cdf0e10cSrcweir private: 509*cdf0e10cSrcweir std::vector< TargetHolder* > maTargetHolders; 510*cdf0e10cSrcweir 511*cdf0e10cSrcweir public: 512*cdf0e10cSrcweir TargetHolders() 513*cdf0e10cSrcweir { 514*cdf0e10cSrcweir maTargetHolders.push_back(new TargetHolder()); 515*cdf0e10cSrcweir } 516*cdf0e10cSrcweir 517*cdf0e10cSrcweir sal_uInt32 size() 518*cdf0e10cSrcweir { 519*cdf0e10cSrcweir return maTargetHolders.size(); 520*cdf0e10cSrcweir } 521*cdf0e10cSrcweir 522*cdf0e10cSrcweir void Push() 523*cdf0e10cSrcweir { 524*cdf0e10cSrcweir maTargetHolders.push_back(new TargetHolder()); 525*cdf0e10cSrcweir } 526*cdf0e10cSrcweir 527*cdf0e10cSrcweir void Pop() 528*cdf0e10cSrcweir { 529*cdf0e10cSrcweir OSL_ENSURE(maTargetHolders.size(), "TargetHolders: POP with no property holders (!)"); 530*cdf0e10cSrcweir if(maTargetHolders.size()) 531*cdf0e10cSrcweir { 532*cdf0e10cSrcweir delete maTargetHolders.back(); 533*cdf0e10cSrcweir maTargetHolders.pop_back(); 534*cdf0e10cSrcweir } 535*cdf0e10cSrcweir } 536*cdf0e10cSrcweir 537*cdf0e10cSrcweir TargetHolder& Current() 538*cdf0e10cSrcweir { 539*cdf0e10cSrcweir OSL_ENSURE(maTargetHolders.size(), "TargetHolders: CURRENT with no property holders (!)"); 540*cdf0e10cSrcweir return *maTargetHolders.back(); 541*cdf0e10cSrcweir } 542*cdf0e10cSrcweir 543*cdf0e10cSrcweir ~TargetHolders() 544*cdf0e10cSrcweir { 545*cdf0e10cSrcweir while(maTargetHolders.size()) 546*cdf0e10cSrcweir { 547*cdf0e10cSrcweir delete maTargetHolders.back(); 548*cdf0e10cSrcweir maTargetHolders.pop_back(); 549*cdf0e10cSrcweir } 550*cdf0e10cSrcweir } 551*cdf0e10cSrcweir }; 552*cdf0e10cSrcweir } // end of anonymous namespace 553*cdf0e10cSrcweir 554*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 555*cdf0e10cSrcweir 556*cdf0e10cSrcweir namespace drawinglayer 557*cdf0e10cSrcweir { 558*cdf0e10cSrcweir namespace primitive2d 559*cdf0e10cSrcweir { 560*cdf0e10cSrcweir /** NonOverlappingFillGradientPrimitive2D class 561*cdf0e10cSrcweir 562*cdf0e10cSrcweir This is a special version of the FillGradientPrimitive2D which decomposes 563*cdf0e10cSrcweir to a non-overlapping geometry version of the gradient. This needs to be 564*cdf0e10cSrcweir used to support the old XOR paint-'trick'. 565*cdf0e10cSrcweir 566*cdf0e10cSrcweir It does not need an own identifier since a renderer who wants to interpret 567*cdf0e10cSrcweir it itself may do so. It just overloads the decomposition of the C++ 568*cdf0e10cSrcweir implementation class to do an alternative decomposition. 569*cdf0e10cSrcweir */ 570*cdf0e10cSrcweir class NonOverlappingFillGradientPrimitive2D : public FillGradientPrimitive2D 571*cdf0e10cSrcweir { 572*cdf0e10cSrcweir protected: 573*cdf0e10cSrcweir /// local decomposition. 574*cdf0e10cSrcweir virtual Primitive2DSequence create2DDecomposition( 575*cdf0e10cSrcweir const geometry::ViewInformation2D& rViewInformation) const; 576*cdf0e10cSrcweir 577*cdf0e10cSrcweir public: 578*cdf0e10cSrcweir /// constructor 579*cdf0e10cSrcweir NonOverlappingFillGradientPrimitive2D( 580*cdf0e10cSrcweir const basegfx::B2DRange& rObjectRange, 581*cdf0e10cSrcweir const attribute::FillGradientAttribute& rFillGradient) 582*cdf0e10cSrcweir : FillGradientPrimitive2D(rObjectRange, rFillGradient) 583*cdf0e10cSrcweir { 584*cdf0e10cSrcweir } 585*cdf0e10cSrcweir }; 586*cdf0e10cSrcweir 587*cdf0e10cSrcweir Primitive2DSequence NonOverlappingFillGradientPrimitive2D::create2DDecomposition( 588*cdf0e10cSrcweir const geometry::ViewInformation2D& /*rViewInformation*/) const 589*cdf0e10cSrcweir { 590*cdf0e10cSrcweir if(!getFillGradient().isDefault()) 591*cdf0e10cSrcweir { 592*cdf0e10cSrcweir return createFill(false); 593*cdf0e10cSrcweir } 594*cdf0e10cSrcweir else 595*cdf0e10cSrcweir { 596*cdf0e10cSrcweir return Primitive2DSequence(); 597*cdf0e10cSrcweir } 598*cdf0e10cSrcweir } 599*cdf0e10cSrcweir } // end of namespace primitive2d 600*cdf0e10cSrcweir } // end of namespace drawinglayer 601*cdf0e10cSrcweir 602*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 603*cdf0e10cSrcweir 604*cdf0e10cSrcweir namespace 605*cdf0e10cSrcweir { 606*cdf0e10cSrcweir /** helper to convert a MapMode to a transformation */ 607*cdf0e10cSrcweir basegfx::B2DHomMatrix getTransformFromMapMode(const MapMode& rMapMode) 608*cdf0e10cSrcweir { 609*cdf0e10cSrcweir basegfx::B2DHomMatrix aMapping; 610*cdf0e10cSrcweir const Fraction aNoScale(1, 1); 611*cdf0e10cSrcweir const Point& rOrigin(rMapMode.GetOrigin()); 612*cdf0e10cSrcweir 613*cdf0e10cSrcweir if(0 != rOrigin.X() || 0 != rOrigin.Y()) 614*cdf0e10cSrcweir { 615*cdf0e10cSrcweir aMapping.translate(rOrigin.X(), rOrigin.Y()); 616*cdf0e10cSrcweir } 617*cdf0e10cSrcweir 618*cdf0e10cSrcweir if(rMapMode.GetScaleX() != aNoScale || rMapMode.GetScaleY() != aNoScale) 619*cdf0e10cSrcweir { 620*cdf0e10cSrcweir aMapping.scale( 621*cdf0e10cSrcweir double(rMapMode.GetScaleX()), 622*cdf0e10cSrcweir double(rMapMode.GetScaleY())); 623*cdf0e10cSrcweir } 624*cdf0e10cSrcweir 625*cdf0e10cSrcweir return aMapping; 626*cdf0e10cSrcweir } 627*cdf0e10cSrcweir 628*cdf0e10cSrcweir /** helper to create a PointArrayPrimitive2D based on current context */ 629*cdf0e10cSrcweir void createPointArrayPrimitive( 630*cdf0e10cSrcweir const std::vector< basegfx::B2DPoint >& rPositions, 631*cdf0e10cSrcweir TargetHolder& rTarget, 632*cdf0e10cSrcweir PropertyHolder& rProperties, 633*cdf0e10cSrcweir basegfx::BColor aBColor) 634*cdf0e10cSrcweir { 635*cdf0e10cSrcweir if(rPositions.size()) 636*cdf0e10cSrcweir { 637*cdf0e10cSrcweir if(rProperties.getTransformation().isIdentity()) 638*cdf0e10cSrcweir { 639*cdf0e10cSrcweir rTarget.append( 640*cdf0e10cSrcweir new drawinglayer::primitive2d::PointArrayPrimitive2D( 641*cdf0e10cSrcweir rPositions, 642*cdf0e10cSrcweir aBColor)); 643*cdf0e10cSrcweir } 644*cdf0e10cSrcweir else 645*cdf0e10cSrcweir { 646*cdf0e10cSrcweir std::vector< basegfx::B2DPoint > aPositions(rPositions); 647*cdf0e10cSrcweir 648*cdf0e10cSrcweir for(sal_uInt32 a(0); a < aPositions.size(); a++) 649*cdf0e10cSrcweir { 650*cdf0e10cSrcweir aPositions[a] = rProperties.getTransformation() * aPositions[a]; 651*cdf0e10cSrcweir } 652*cdf0e10cSrcweir 653*cdf0e10cSrcweir rTarget.append( 654*cdf0e10cSrcweir new drawinglayer::primitive2d::PointArrayPrimitive2D( 655*cdf0e10cSrcweir aPositions, 656*cdf0e10cSrcweir aBColor)); 657*cdf0e10cSrcweir } 658*cdf0e10cSrcweir } 659*cdf0e10cSrcweir } 660*cdf0e10cSrcweir 661*cdf0e10cSrcweir /** helper to create a PolygonHairlinePrimitive2D based on current context */ 662*cdf0e10cSrcweir void createHairlinePrimitive( 663*cdf0e10cSrcweir const basegfx::B2DPolygon& rLinePolygon, 664*cdf0e10cSrcweir TargetHolder& rTarget, 665*cdf0e10cSrcweir PropertyHolder& rProperties) 666*cdf0e10cSrcweir { 667*cdf0e10cSrcweir if(rLinePolygon.count()) 668*cdf0e10cSrcweir { 669*cdf0e10cSrcweir basegfx::B2DPolygon aLinePolygon(rLinePolygon); 670*cdf0e10cSrcweir aLinePolygon.transform(rProperties.getTransformation()); 671*cdf0e10cSrcweir rTarget.append( 672*cdf0e10cSrcweir new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( 673*cdf0e10cSrcweir aLinePolygon, 674*cdf0e10cSrcweir rProperties.getLineColor())); 675*cdf0e10cSrcweir } 676*cdf0e10cSrcweir } 677*cdf0e10cSrcweir 678*cdf0e10cSrcweir /** helper to create a PolyPolygonColorPrimitive2D based on current context */ 679*cdf0e10cSrcweir void createFillPrimitive( 680*cdf0e10cSrcweir const basegfx::B2DPolyPolygon& rFillPolyPolygon, 681*cdf0e10cSrcweir TargetHolder& rTarget, 682*cdf0e10cSrcweir PropertyHolder& rProperties) 683*cdf0e10cSrcweir { 684*cdf0e10cSrcweir if(rFillPolyPolygon.count()) 685*cdf0e10cSrcweir { 686*cdf0e10cSrcweir basegfx::B2DPolyPolygon aFillPolyPolygon(rFillPolyPolygon); 687*cdf0e10cSrcweir aFillPolyPolygon.transform(rProperties.getTransformation()); 688*cdf0e10cSrcweir rTarget.append( 689*cdf0e10cSrcweir new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( 690*cdf0e10cSrcweir aFillPolyPolygon, 691*cdf0e10cSrcweir rProperties.getFillColor())); 692*cdf0e10cSrcweir } 693*cdf0e10cSrcweir } 694*cdf0e10cSrcweir 695*cdf0e10cSrcweir /** helper to create a PolygonStrokePrimitive2D based on current context */ 696*cdf0e10cSrcweir void createLinePrimitive( 697*cdf0e10cSrcweir const basegfx::B2DPolygon& rLinePolygon, 698*cdf0e10cSrcweir const LineInfo& rLineInfo, 699*cdf0e10cSrcweir TargetHolder& rTarget, 700*cdf0e10cSrcweir PropertyHolder& rProperties) 701*cdf0e10cSrcweir { 702*cdf0e10cSrcweir if(rLinePolygon.count()) 703*cdf0e10cSrcweir { 704*cdf0e10cSrcweir const bool bDashDotUsed(LINE_DASH == rLineInfo.GetStyle()); 705*cdf0e10cSrcweir const bool bWidthUsed(rLineInfo.GetWidth() > 1); 706*cdf0e10cSrcweir 707*cdf0e10cSrcweir if(bDashDotUsed || bWidthUsed) 708*cdf0e10cSrcweir { 709*cdf0e10cSrcweir basegfx::B2DPolygon aLinePolygon(rLinePolygon); 710*cdf0e10cSrcweir aLinePolygon.transform(rProperties.getTransformation()); 711*cdf0e10cSrcweir const drawinglayer::attribute::LineAttribute aLineAttribute( 712*cdf0e10cSrcweir rProperties.getLineColor(), 713*cdf0e10cSrcweir bWidthUsed ? rLineInfo.GetWidth() : 0.0, 714*cdf0e10cSrcweir rLineInfo.GetLineJoin()); 715*cdf0e10cSrcweir 716*cdf0e10cSrcweir if(bDashDotUsed) 717*cdf0e10cSrcweir { 718*cdf0e10cSrcweir ::std::vector< double > fDotDashArray; 719*cdf0e10cSrcweir const double fDashLen(rLineInfo.GetDashLen()); 720*cdf0e10cSrcweir const double fDotLen(rLineInfo.GetDotLen()); 721*cdf0e10cSrcweir const double fDistance(rLineInfo.GetDistance()); 722*cdf0e10cSrcweir 723*cdf0e10cSrcweir for(sal_uInt16 a(0); a < rLineInfo.GetDashCount(); a++) 724*cdf0e10cSrcweir { 725*cdf0e10cSrcweir fDotDashArray.push_back(fDashLen); 726*cdf0e10cSrcweir fDotDashArray.push_back(fDistance); 727*cdf0e10cSrcweir } 728*cdf0e10cSrcweir 729*cdf0e10cSrcweir for(sal_uInt16 b(0); b < rLineInfo.GetDotCount(); b++) 730*cdf0e10cSrcweir { 731*cdf0e10cSrcweir fDotDashArray.push_back(fDotLen); 732*cdf0e10cSrcweir fDotDashArray.push_back(fDistance); 733*cdf0e10cSrcweir } 734*cdf0e10cSrcweir 735*cdf0e10cSrcweir const double fAccumulated(::std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0)); 736*cdf0e10cSrcweir const drawinglayer::attribute::StrokeAttribute aStrokeAttribute( 737*cdf0e10cSrcweir fDotDashArray, 738*cdf0e10cSrcweir fAccumulated); 739*cdf0e10cSrcweir 740*cdf0e10cSrcweir rTarget.append( 741*cdf0e10cSrcweir new drawinglayer::primitive2d::PolygonStrokePrimitive2D( 742*cdf0e10cSrcweir aLinePolygon, 743*cdf0e10cSrcweir aLineAttribute, 744*cdf0e10cSrcweir aStrokeAttribute)); 745*cdf0e10cSrcweir } 746*cdf0e10cSrcweir else 747*cdf0e10cSrcweir { 748*cdf0e10cSrcweir rTarget.append( 749*cdf0e10cSrcweir new drawinglayer::primitive2d::PolygonStrokePrimitive2D( 750*cdf0e10cSrcweir aLinePolygon, 751*cdf0e10cSrcweir aLineAttribute)); 752*cdf0e10cSrcweir } 753*cdf0e10cSrcweir } 754*cdf0e10cSrcweir else 755*cdf0e10cSrcweir { 756*cdf0e10cSrcweir createHairlinePrimitive(rLinePolygon, rTarget, rProperties); 757*cdf0e10cSrcweir } 758*cdf0e10cSrcweir } 759*cdf0e10cSrcweir } 760*cdf0e10cSrcweir 761*cdf0e10cSrcweir /** helper to create needed line and fill primitives based on current context */ 762*cdf0e10cSrcweir void createHairlineAndFillPrimitive( 763*cdf0e10cSrcweir const basegfx::B2DPolygon& rPolygon, 764*cdf0e10cSrcweir TargetHolder& rTarget, 765*cdf0e10cSrcweir PropertyHolder& rProperties) 766*cdf0e10cSrcweir { 767*cdf0e10cSrcweir if(rProperties.getFillColorActive()) 768*cdf0e10cSrcweir { 769*cdf0e10cSrcweir createFillPrimitive(basegfx::B2DPolyPolygon(rPolygon), rTarget, rProperties); 770*cdf0e10cSrcweir } 771*cdf0e10cSrcweir 772*cdf0e10cSrcweir if(rProperties.getLineColorActive()) 773*cdf0e10cSrcweir { 774*cdf0e10cSrcweir createHairlinePrimitive(rPolygon, rTarget, rProperties); 775*cdf0e10cSrcweir } 776*cdf0e10cSrcweir } 777*cdf0e10cSrcweir 778*cdf0e10cSrcweir /** helper to create needed line and fill primitives based on current context */ 779*cdf0e10cSrcweir void createHairlineAndFillPrimitive( 780*cdf0e10cSrcweir const basegfx::B2DPolyPolygon& rPolyPolygon, 781*cdf0e10cSrcweir TargetHolder& rTarget, 782*cdf0e10cSrcweir PropertyHolder& rProperties) 783*cdf0e10cSrcweir { 784*cdf0e10cSrcweir if(rProperties.getFillColorActive()) 785*cdf0e10cSrcweir { 786*cdf0e10cSrcweir createFillPrimitive(rPolyPolygon, rTarget, rProperties); 787*cdf0e10cSrcweir } 788*cdf0e10cSrcweir 789*cdf0e10cSrcweir if(rProperties.getLineColorActive()) 790*cdf0e10cSrcweir { 791*cdf0e10cSrcweir for(sal_uInt32 a(0); a < rPolyPolygon.count(); a++) 792*cdf0e10cSrcweir { 793*cdf0e10cSrcweir createHairlinePrimitive(rPolyPolygon.getB2DPolygon(a), rTarget, rProperties); 794*cdf0e10cSrcweir } 795*cdf0e10cSrcweir } 796*cdf0e10cSrcweir } 797*cdf0e10cSrcweir 798*cdf0e10cSrcweir /** helper to create DiscreteBitmapPrimitive2D based on current context. 799*cdf0e10cSrcweir The DiscreteBitmapPrimitive2D is especially created for this usage 800*cdf0e10cSrcweir since no other usage defines a bitmap visualisation based on top-left 801*cdf0e10cSrcweir position and size in pixels. At the end it will create a view-dependent 802*cdf0e10cSrcweir transformed embedding of a BitmapPrimitive2D. 803*cdf0e10cSrcweir */ 804*cdf0e10cSrcweir void createBitmapExPrimitive( 805*cdf0e10cSrcweir const BitmapEx& rBitmapEx, 806*cdf0e10cSrcweir const Point& rPoint, 807*cdf0e10cSrcweir TargetHolder& rTarget, 808*cdf0e10cSrcweir PropertyHolder& rProperties) 809*cdf0e10cSrcweir { 810*cdf0e10cSrcweir if(!rBitmapEx.IsEmpty()) 811*cdf0e10cSrcweir { 812*cdf0e10cSrcweir basegfx::B2DPoint aPoint(rPoint.X(), rPoint.Y()); 813*cdf0e10cSrcweir aPoint = rProperties.getTransformation() * aPoint; 814*cdf0e10cSrcweir 815*cdf0e10cSrcweir rTarget.append( 816*cdf0e10cSrcweir new drawinglayer::primitive2d::DiscreteBitmapPrimitive2D( 817*cdf0e10cSrcweir rBitmapEx, 818*cdf0e10cSrcweir aPoint)); 819*cdf0e10cSrcweir } 820*cdf0e10cSrcweir } 821*cdf0e10cSrcweir 822*cdf0e10cSrcweir /** helper to create BitmapPrimitive2D based on current context */ 823*cdf0e10cSrcweir void createBitmapExPrimitive( 824*cdf0e10cSrcweir const BitmapEx& rBitmapEx, 825*cdf0e10cSrcweir const Point& rPoint, 826*cdf0e10cSrcweir const Size& rSize, 827*cdf0e10cSrcweir TargetHolder& rTarget, 828*cdf0e10cSrcweir PropertyHolder& rProperties) 829*cdf0e10cSrcweir { 830*cdf0e10cSrcweir if(!rBitmapEx.IsEmpty()) 831*cdf0e10cSrcweir { 832*cdf0e10cSrcweir basegfx::B2DHomMatrix aObjectTransform; 833*cdf0e10cSrcweir 834*cdf0e10cSrcweir aObjectTransform.set(0, 0, rSize.Width()); 835*cdf0e10cSrcweir aObjectTransform.set(1, 1, rSize.Height()); 836*cdf0e10cSrcweir aObjectTransform.set(0, 2, rPoint.X()); 837*cdf0e10cSrcweir aObjectTransform.set(1, 2, rPoint.Y()); 838*cdf0e10cSrcweir 839*cdf0e10cSrcweir aObjectTransform = rProperties.getTransformation() * aObjectTransform; 840*cdf0e10cSrcweir 841*cdf0e10cSrcweir rTarget.append( 842*cdf0e10cSrcweir new drawinglayer::primitive2d::BitmapPrimitive2D( 843*cdf0e10cSrcweir rBitmapEx, 844*cdf0e10cSrcweir aObjectTransform)); 845*cdf0e10cSrcweir } 846*cdf0e10cSrcweir } 847*cdf0e10cSrcweir 848*cdf0e10cSrcweir /** helper to create a regular BotmapEx from a MaskAction (definitions 849*cdf0e10cSrcweir which use a bitmap without transparence but define one of the colors as 850*cdf0e10cSrcweir transparent) 851*cdf0e10cSrcweir */ 852*cdf0e10cSrcweir BitmapEx createMaskBmpEx(const Bitmap& rBitmap, const Color& rMaskColor) 853*cdf0e10cSrcweir { 854*cdf0e10cSrcweir const Color aWhite(COL_WHITE); 855*cdf0e10cSrcweir BitmapPalette aBiLevelPalette(2); 856*cdf0e10cSrcweir 857*cdf0e10cSrcweir aBiLevelPalette[0] = aWhite; 858*cdf0e10cSrcweir aBiLevelPalette[1] = rMaskColor; 859*cdf0e10cSrcweir 860*cdf0e10cSrcweir Bitmap aMask(rBitmap.CreateMask(aWhite)); 861*cdf0e10cSrcweir Bitmap aSolid(rBitmap.GetSizePixel(), 1, &aBiLevelPalette); 862*cdf0e10cSrcweir 863*cdf0e10cSrcweir aSolid.Erase(rMaskColor); 864*cdf0e10cSrcweir 865*cdf0e10cSrcweir return BitmapEx(aSolid, aMask); 866*cdf0e10cSrcweir } 867*cdf0e10cSrcweir 868*cdf0e10cSrcweir /** helper to convert from a VCL Gradient definition to the corresponding 869*cdf0e10cSrcweir data for primitive representation 870*cdf0e10cSrcweir */ 871*cdf0e10cSrcweir drawinglayer::attribute::FillGradientAttribute createFillGradientAttribute(const Gradient& rGradient) 872*cdf0e10cSrcweir { 873*cdf0e10cSrcweir const Color aStartColor(rGradient.GetStartColor()); 874*cdf0e10cSrcweir const sal_uInt16 nStartIntens(rGradient.GetStartIntensity()); 875*cdf0e10cSrcweir basegfx::BColor aStart(aStartColor.getBColor()); 876*cdf0e10cSrcweir 877*cdf0e10cSrcweir if(nStartIntens != 100) 878*cdf0e10cSrcweir { 879*cdf0e10cSrcweir const basegfx::BColor aBlack; 880*cdf0e10cSrcweir aStart = interpolate(aBlack, aStart, (double)nStartIntens * 0.01); 881*cdf0e10cSrcweir } 882*cdf0e10cSrcweir 883*cdf0e10cSrcweir const Color aEndColor(rGradient.GetEndColor()); 884*cdf0e10cSrcweir const sal_uInt16 nEndIntens(rGradient.GetEndIntensity()); 885*cdf0e10cSrcweir basegfx::BColor aEnd(aEndColor.getBColor()); 886*cdf0e10cSrcweir 887*cdf0e10cSrcweir if(nEndIntens != 100) 888*cdf0e10cSrcweir { 889*cdf0e10cSrcweir const basegfx::BColor aBlack; 890*cdf0e10cSrcweir aEnd = interpolate(aBlack, aEnd, (double)nEndIntens * 0.01); 891*cdf0e10cSrcweir } 892*cdf0e10cSrcweir 893*cdf0e10cSrcweir drawinglayer::attribute::GradientStyle aGradientStyle(drawinglayer::attribute::GRADIENTSTYLE_RECT); 894*cdf0e10cSrcweir 895*cdf0e10cSrcweir switch(rGradient.GetStyle()) 896*cdf0e10cSrcweir { 897*cdf0e10cSrcweir case GRADIENT_LINEAR : 898*cdf0e10cSrcweir { 899*cdf0e10cSrcweir aGradientStyle = drawinglayer::attribute::GRADIENTSTYLE_LINEAR; 900*cdf0e10cSrcweir break; 901*cdf0e10cSrcweir } 902*cdf0e10cSrcweir case GRADIENT_AXIAL : 903*cdf0e10cSrcweir { 904*cdf0e10cSrcweir aGradientStyle = drawinglayer::attribute::GRADIENTSTYLE_AXIAL; 905*cdf0e10cSrcweir break; 906*cdf0e10cSrcweir } 907*cdf0e10cSrcweir case GRADIENT_RADIAL : 908*cdf0e10cSrcweir { 909*cdf0e10cSrcweir aGradientStyle = drawinglayer::attribute::GRADIENTSTYLE_RADIAL; 910*cdf0e10cSrcweir break; 911*cdf0e10cSrcweir } 912*cdf0e10cSrcweir case GRADIENT_ELLIPTICAL : 913*cdf0e10cSrcweir { 914*cdf0e10cSrcweir aGradientStyle = drawinglayer::attribute::GRADIENTSTYLE_ELLIPTICAL; 915*cdf0e10cSrcweir break; 916*cdf0e10cSrcweir } 917*cdf0e10cSrcweir case GRADIENT_SQUARE : 918*cdf0e10cSrcweir { 919*cdf0e10cSrcweir aGradientStyle = drawinglayer::attribute::GRADIENTSTYLE_SQUARE; 920*cdf0e10cSrcweir break; 921*cdf0e10cSrcweir } 922*cdf0e10cSrcweir default : // GRADIENT_RECT 923*cdf0e10cSrcweir { 924*cdf0e10cSrcweir aGradientStyle = drawinglayer::attribute::GRADIENTSTYLE_RECT; 925*cdf0e10cSrcweir break; 926*cdf0e10cSrcweir } 927*cdf0e10cSrcweir } 928*cdf0e10cSrcweir 929*cdf0e10cSrcweir return drawinglayer::attribute::FillGradientAttribute( 930*cdf0e10cSrcweir aGradientStyle, 931*cdf0e10cSrcweir (double)rGradient.GetBorder() * 0.01, 932*cdf0e10cSrcweir (double)rGradient.GetOfsX() * 0.01, 933*cdf0e10cSrcweir (double)rGradient.GetOfsY() * 0.01, 934*cdf0e10cSrcweir (double)rGradient.GetAngle() * F_PI1800, 935*cdf0e10cSrcweir aStart, 936*cdf0e10cSrcweir aEnd, 937*cdf0e10cSrcweir rGradient.GetSteps()); 938*cdf0e10cSrcweir } 939*cdf0e10cSrcweir 940*cdf0e10cSrcweir /** helper to convert from a VCL Hatch definition to the corresponding 941*cdf0e10cSrcweir data for primitive representation 942*cdf0e10cSrcweir */ 943*cdf0e10cSrcweir drawinglayer::attribute::FillHatchAttribute createFillHatchAttribute(const Hatch& rHatch) 944*cdf0e10cSrcweir { 945*cdf0e10cSrcweir drawinglayer::attribute::HatchStyle aHatchStyle(drawinglayer::attribute::HATCHSTYLE_SINGLE); 946*cdf0e10cSrcweir 947*cdf0e10cSrcweir switch(rHatch.GetStyle()) 948*cdf0e10cSrcweir { 949*cdf0e10cSrcweir default : // case HATCH_SINGLE : 950*cdf0e10cSrcweir { 951*cdf0e10cSrcweir aHatchStyle = drawinglayer::attribute::HATCHSTYLE_SINGLE; 952*cdf0e10cSrcweir break; 953*cdf0e10cSrcweir } 954*cdf0e10cSrcweir case HATCH_DOUBLE : 955*cdf0e10cSrcweir { 956*cdf0e10cSrcweir aHatchStyle = drawinglayer::attribute::HATCHSTYLE_DOUBLE; 957*cdf0e10cSrcweir break; 958*cdf0e10cSrcweir } 959*cdf0e10cSrcweir case HATCH_TRIPLE : 960*cdf0e10cSrcweir { 961*cdf0e10cSrcweir aHatchStyle = drawinglayer::attribute::HATCHSTYLE_TRIPLE; 962*cdf0e10cSrcweir break; 963*cdf0e10cSrcweir } 964*cdf0e10cSrcweir } 965*cdf0e10cSrcweir 966*cdf0e10cSrcweir return drawinglayer::attribute::FillHatchAttribute( 967*cdf0e10cSrcweir aHatchStyle, 968*cdf0e10cSrcweir (double)rHatch.GetDistance(), 969*cdf0e10cSrcweir (double)rHatch.GetAngle() * F_PI1800, 970*cdf0e10cSrcweir rHatch.GetColor().getBColor(), 971*cdf0e10cSrcweir false); 972*cdf0e10cSrcweir } 973*cdf0e10cSrcweir 974*cdf0e10cSrcweir /** helper to take needed action on ClipRegion change. This method needs to be called 975*cdf0e10cSrcweir on any Region change, e.g. at the obvious actions doing this, but also at pop-calls 976*cdf0e10cSrcweir whcih change the Region of the current context. It takes care of creating the 977*cdf0e10cSrcweir current embeddec context, set the new Region at the context and eventually prepare 978*cdf0e10cSrcweir a new target for embracing new geometry to the current region 979*cdf0e10cSrcweir */ 980*cdf0e10cSrcweir void HandleNewClipRegion( 981*cdf0e10cSrcweir const basegfx::B2DPolyPolygon& rClipPolyPolygon, 982*cdf0e10cSrcweir TargetHolders& rTargetHolders, 983*cdf0e10cSrcweir PropertyHolders& rPropertyHolders) 984*cdf0e10cSrcweir { 985*cdf0e10cSrcweir const bool bNewActive(rClipPolyPolygon.count()); 986*cdf0e10cSrcweir 987*cdf0e10cSrcweir // #i108636# The handlig of new ClipPolyPolygons was not done as good as possible 988*cdf0e10cSrcweir // in the first version of this interpreter; e.g. when a ClipPolyPolygon was set 989*cdf0e10cSrcweir // initially and then using a lot of push/pop actions, the pop always leads 990*cdf0e10cSrcweir // to setting a 'new' ClipPolyPolygon which indeed is the return to the ClipPolyPolygon 991*cdf0e10cSrcweir // of the properties next on the stack. 992*cdf0e10cSrcweir // 993*cdf0e10cSrcweir // This ClipPolyPolygon is identical to the current one, so there is no need to 994*cdf0e10cSrcweir // create a MaskPrimitive2D containing the up-to-now created primitives, but 995*cdf0e10cSrcweir // this was done before. While this does not lead to wrong primitive 996*cdf0e10cSrcweir // representations of the metafile data, it creates unneccesarily expensive 997*cdf0e10cSrcweir // representations. Just detecting when no really 'new' ClipPolyPolygon gets set 998*cdf0e10cSrcweir // solves the problem. 999*cdf0e10cSrcweir 1000*cdf0e10cSrcweir if(!rPropertyHolders.Current().getClipPolyPolygonActive() && !bNewActive) 1001*cdf0e10cSrcweir { 1002*cdf0e10cSrcweir // no active ClipPolyPolygon exchanged by no new one, done 1003*cdf0e10cSrcweir return; 1004*cdf0e10cSrcweir } 1005*cdf0e10cSrcweir 1006*cdf0e10cSrcweir if(rPropertyHolders.Current().getClipPolyPolygonActive() && bNewActive) 1007*cdf0e10cSrcweir { 1008*cdf0e10cSrcweir // active ClipPolyPolygon and new active ClipPolyPolygon 1009*cdf0e10cSrcweir if(rPropertyHolders.Current().getClipPolyPolygon() == rClipPolyPolygon) 1010*cdf0e10cSrcweir { 1011*cdf0e10cSrcweir // new is the same as old, done 1012*cdf0e10cSrcweir return; 1013*cdf0e10cSrcweir } 1014*cdf0e10cSrcweir } 1015*cdf0e10cSrcweir 1016*cdf0e10cSrcweir // Here the old and the new are definitively different, maybe 1017*cdf0e10cSrcweir // old one and/or new one is not active. 1018*cdf0e10cSrcweir 1019*cdf0e10cSrcweir // Handle deletion of old ClipPolyPolygon. The process evtl. created primitives which 1020*cdf0e10cSrcweir // belong to this active ClipPolyPolygon. These need to be embedded to a 1021*cdf0e10cSrcweir // MaskPrimitive2D accordingly. 1022*cdf0e10cSrcweir if(rPropertyHolders.Current().getClipPolyPolygonActive() && rTargetHolders.size() > 1) 1023*cdf0e10cSrcweir { 1024*cdf0e10cSrcweir drawinglayer::primitive2d::Primitive2DSequence aSubContent; 1025*cdf0e10cSrcweir 1026*cdf0e10cSrcweir if(rPropertyHolders.Current().getClipPolyPolygon().count() 1027*cdf0e10cSrcweir && rTargetHolders.Current().size()) 1028*cdf0e10cSrcweir { 1029*cdf0e10cSrcweir aSubContent = rTargetHolders.Current().getPrimitive2DSequence( 1030*cdf0e10cSrcweir rPropertyHolders.Current()); 1031*cdf0e10cSrcweir } 1032*cdf0e10cSrcweir 1033*cdf0e10cSrcweir rTargetHolders.Pop(); 1034*cdf0e10cSrcweir 1035*cdf0e10cSrcweir if(aSubContent.hasElements()) 1036*cdf0e10cSrcweir { 1037*cdf0e10cSrcweir rTargetHolders.Current().append( 1038*cdf0e10cSrcweir new drawinglayer::primitive2d::GroupPrimitive2D( 1039*cdf0e10cSrcweir aSubContent)); 1040*cdf0e10cSrcweir } 1041*cdf0e10cSrcweir } 1042*cdf0e10cSrcweir 1043*cdf0e10cSrcweir // apply new settings to current properties by setting 1044*cdf0e10cSrcweir // the new region now 1045*cdf0e10cSrcweir rPropertyHolders.Current().setClipPolyPolygonActive(bNewActive); 1046*cdf0e10cSrcweir 1047*cdf0e10cSrcweir if(bNewActive) 1048*cdf0e10cSrcweir { 1049*cdf0e10cSrcweir rPropertyHolders.Current().setClipPolyPolygon(rClipPolyPolygon); 1050*cdf0e10cSrcweir 1051*cdf0e10cSrcweir // prepare new content holder for new active region 1052*cdf0e10cSrcweir rTargetHolders.Push(); 1053*cdf0e10cSrcweir } 1054*cdf0e10cSrcweir } 1055*cdf0e10cSrcweir 1056*cdf0e10cSrcweir /** helper to handle the change of RasterOp. It takes care of encapsulating all current 1057*cdf0e10cSrcweir geometry to the current RasterOp (if changed) and needs to be called on any RasterOp 1058*cdf0e10cSrcweir change. It will also start a new geometry target to embrace to the new RasterOp if 1059*cdf0e10cSrcweir a changuing RasterOp is used. Currently, ROP_XOR and ROP_INVERT are supported using 1060*cdf0e10cSrcweir InvertPrimitive2D, and ROP_0 by using a ModifiedColorPrimitive2D to force to black paint 1061*cdf0e10cSrcweir */ 1062*cdf0e10cSrcweir void HandleNewRasterOp( 1063*cdf0e10cSrcweir RasterOp aRasterOp, 1064*cdf0e10cSrcweir TargetHolders& rTargetHolders, 1065*cdf0e10cSrcweir PropertyHolders& rPropertyHolders) 1066*cdf0e10cSrcweir { 1067*cdf0e10cSrcweir // check if currently active 1068*cdf0e10cSrcweir if(rPropertyHolders.Current().isRasterOpActive() && rTargetHolders.size() > 1) 1069*cdf0e10cSrcweir { 1070*cdf0e10cSrcweir drawinglayer::primitive2d::Primitive2DSequence aSubContent; 1071*cdf0e10cSrcweir 1072*cdf0e10cSrcweir if(rTargetHolders.Current().size()) 1073*cdf0e10cSrcweir { 1074*cdf0e10cSrcweir aSubContent = rTargetHolders.Current().getPrimitive2DSequence(rPropertyHolders.Current()); 1075*cdf0e10cSrcweir } 1076*cdf0e10cSrcweir 1077*cdf0e10cSrcweir rTargetHolders.Pop(); 1078*cdf0e10cSrcweir 1079*cdf0e10cSrcweir if(aSubContent.hasElements()) 1080*cdf0e10cSrcweir { 1081*cdf0e10cSrcweir if(rPropertyHolders.Current().isRasterOpForceBlack()) 1082*cdf0e10cSrcweir { 1083*cdf0e10cSrcweir // force content to black 1084*cdf0e10cSrcweir rTargetHolders.Current().append( 1085*cdf0e10cSrcweir new drawinglayer::primitive2d::ModifiedColorPrimitive2D( 1086*cdf0e10cSrcweir aSubContent, 1087*cdf0e10cSrcweir basegfx::BColorModifier(basegfx::BColor(0.0, 0.0, 0.0)))); 1088*cdf0e10cSrcweir } 1089*cdf0e10cSrcweir else // if(rPropertyHolders.Current().isRasterOpInvert()) 1090*cdf0e10cSrcweir { 1091*cdf0e10cSrcweir // invert content 1092*cdf0e10cSrcweir rTargetHolders.Current().append( 1093*cdf0e10cSrcweir new drawinglayer::primitive2d::InvertPrimitive2D( 1094*cdf0e10cSrcweir aSubContent)); 1095*cdf0e10cSrcweir } 1096*cdf0e10cSrcweir } 1097*cdf0e10cSrcweir } 1098*cdf0e10cSrcweir 1099*cdf0e10cSrcweir // apply new settings 1100*cdf0e10cSrcweir rPropertyHolders.Current().setRasterOp(aRasterOp); 1101*cdf0e10cSrcweir 1102*cdf0e10cSrcweir // check if now active 1103*cdf0e10cSrcweir if(rPropertyHolders.Current().isRasterOpActive()) 1104*cdf0e10cSrcweir { 1105*cdf0e10cSrcweir // prepare new content holder for new invert 1106*cdf0e10cSrcweir rTargetHolders.Push(); 1107*cdf0e10cSrcweir } 1108*cdf0e10cSrcweir } 1109*cdf0e10cSrcweir 1110*cdf0e10cSrcweir /** helper to create needed data to emulate the VCL Wallpaper Metafile action. 1111*cdf0e10cSrcweir It is a quite mighty action. This helper is for simple color filled background. 1112*cdf0e10cSrcweir */ 1113*cdf0e10cSrcweir drawinglayer::primitive2d::BasePrimitive2D* CreateColorWallpaper( 1114*cdf0e10cSrcweir const basegfx::B2DRange& rRange, 1115*cdf0e10cSrcweir const basegfx::BColor& rColor, 1116*cdf0e10cSrcweir PropertyHolder& rPropertyHolder) 1117*cdf0e10cSrcweir { 1118*cdf0e10cSrcweir basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(rRange)); 1119*cdf0e10cSrcweir aOutline.transform(rPropertyHolder.getTransformation()); 1120*cdf0e10cSrcweir 1121*cdf0e10cSrcweir return new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( 1122*cdf0e10cSrcweir basegfx::B2DPolyPolygon(aOutline), 1123*cdf0e10cSrcweir rColor); 1124*cdf0e10cSrcweir } 1125*cdf0e10cSrcweir 1126*cdf0e10cSrcweir /** helper to create needed data to emulate the VCL Wallpaper Metafile action. 1127*cdf0e10cSrcweir It is a quite mighty action. This helper is for gradient filled background. 1128*cdf0e10cSrcweir */ 1129*cdf0e10cSrcweir drawinglayer::primitive2d::BasePrimitive2D* CreateGradientWallpaper( 1130*cdf0e10cSrcweir const basegfx::B2DRange& rRange, 1131*cdf0e10cSrcweir const Gradient& rGradient, 1132*cdf0e10cSrcweir PropertyHolder& rPropertyHolder) 1133*cdf0e10cSrcweir { 1134*cdf0e10cSrcweir const drawinglayer::attribute::FillGradientAttribute aAttribute(createFillGradientAttribute(rGradient)); 1135*cdf0e10cSrcweir 1136*cdf0e10cSrcweir if(aAttribute.getStartColor() == aAttribute.getEndColor()) 1137*cdf0e10cSrcweir { 1138*cdf0e10cSrcweir // not really a gradient. Create filled rectangle 1139*cdf0e10cSrcweir return CreateColorWallpaper(rRange, aAttribute.getStartColor(), rPropertyHolder); 1140*cdf0e10cSrcweir } 1141*cdf0e10cSrcweir else 1142*cdf0e10cSrcweir { 1143*cdf0e10cSrcweir // really a gradient 1144*cdf0e10cSrcweir drawinglayer::primitive2d::BasePrimitive2D* pRetval = 1145*cdf0e10cSrcweir new drawinglayer::primitive2d::FillGradientPrimitive2D( 1146*cdf0e10cSrcweir rRange, 1147*cdf0e10cSrcweir aAttribute); 1148*cdf0e10cSrcweir 1149*cdf0e10cSrcweir if(!rPropertyHolder.getTransformation().isIdentity()) 1150*cdf0e10cSrcweir { 1151*cdf0e10cSrcweir const drawinglayer::primitive2d::Primitive2DReference xPrim(pRetval); 1152*cdf0e10cSrcweir const drawinglayer::primitive2d::Primitive2DSequence xSeq(&xPrim, 1); 1153*cdf0e10cSrcweir 1154*cdf0e10cSrcweir pRetval = new drawinglayer::primitive2d::TransformPrimitive2D( 1155*cdf0e10cSrcweir rPropertyHolder.getTransformation(), 1156*cdf0e10cSrcweir xSeq); 1157*cdf0e10cSrcweir } 1158*cdf0e10cSrcweir 1159*cdf0e10cSrcweir return pRetval; 1160*cdf0e10cSrcweir } 1161*cdf0e10cSrcweir } 1162*cdf0e10cSrcweir 1163*cdf0e10cSrcweir /** helper to create needed data to emulate the VCL Wallpaper Metafile action. 1164*cdf0e10cSrcweir It is a quite mighty action. This helper decides if color and/or gradient 1165*cdf0e10cSrcweir background is needed for the wnated bitmap fill and then creates the needed 1166*cdf0e10cSrcweir WallpaperBitmapPrimitive2D. This primitive was created for this purpose and 1167*cdf0e10cSrcweir takes over all needed logic of orientations and tiling. 1168*cdf0e10cSrcweir */ 1169*cdf0e10cSrcweir void CreateAndAppendBitmapWallpaper( 1170*cdf0e10cSrcweir basegfx::B2DRange aWallpaperRange, 1171*cdf0e10cSrcweir const Wallpaper& rWallpaper, 1172*cdf0e10cSrcweir TargetHolder& rTarget, 1173*cdf0e10cSrcweir PropertyHolder& rProperty) 1174*cdf0e10cSrcweir { 1175*cdf0e10cSrcweir const BitmapEx aBitmapEx(rWallpaper.GetBitmap()); 1176*cdf0e10cSrcweir const WallpaperStyle eWallpaperStyle(rWallpaper.GetStyle()); 1177*cdf0e10cSrcweir 1178*cdf0e10cSrcweir // if bitmap visualisation is transparent, maybe background 1179*cdf0e10cSrcweir // needs to be filled. Create background 1180*cdf0e10cSrcweir if(aBitmapEx.IsTransparent() 1181*cdf0e10cSrcweir || (WALLPAPER_TILE != eWallpaperStyle && WALLPAPER_SCALE != eWallpaperStyle)) 1182*cdf0e10cSrcweir { 1183*cdf0e10cSrcweir if(rWallpaper.IsGradient()) 1184*cdf0e10cSrcweir { 1185*cdf0e10cSrcweir rTarget.append( 1186*cdf0e10cSrcweir CreateGradientWallpaper( 1187*cdf0e10cSrcweir aWallpaperRange, 1188*cdf0e10cSrcweir rWallpaper.GetGradient(), 1189*cdf0e10cSrcweir rProperty)); 1190*cdf0e10cSrcweir } 1191*cdf0e10cSrcweir else if(!rWallpaper.GetColor().GetTransparency()) 1192*cdf0e10cSrcweir { 1193*cdf0e10cSrcweir rTarget.append( 1194*cdf0e10cSrcweir CreateColorWallpaper( 1195*cdf0e10cSrcweir aWallpaperRange, 1196*cdf0e10cSrcweir rWallpaper.GetColor().getBColor(), 1197*cdf0e10cSrcweir rProperty)); 1198*cdf0e10cSrcweir } 1199*cdf0e10cSrcweir } 1200*cdf0e10cSrcweir 1201*cdf0e10cSrcweir // use wallpaper rect if set 1202*cdf0e10cSrcweir if(rWallpaper.IsRect() && !rWallpaper.GetRect().IsEmpty()) 1203*cdf0e10cSrcweir { 1204*cdf0e10cSrcweir aWallpaperRange = basegfx::B2DRange( 1205*cdf0e10cSrcweir rWallpaper.GetRect().Left(), rWallpaper.GetRect().Top(), 1206*cdf0e10cSrcweir rWallpaper.GetRect().Right(), rWallpaper.GetRect().Bottom()); 1207*cdf0e10cSrcweir } 1208*cdf0e10cSrcweir 1209*cdf0e10cSrcweir drawinglayer::primitive2d::BasePrimitive2D* pBitmapWallpaperFill = 1210*cdf0e10cSrcweir new drawinglayer::primitive2d::WallpaperBitmapPrimitive2D( 1211*cdf0e10cSrcweir aWallpaperRange, 1212*cdf0e10cSrcweir aBitmapEx, 1213*cdf0e10cSrcweir eWallpaperStyle); 1214*cdf0e10cSrcweir 1215*cdf0e10cSrcweir if(rProperty.getTransformation().isIdentity()) 1216*cdf0e10cSrcweir { 1217*cdf0e10cSrcweir // add directly 1218*cdf0e10cSrcweir rTarget.append(pBitmapWallpaperFill); 1219*cdf0e10cSrcweir } 1220*cdf0e10cSrcweir else 1221*cdf0e10cSrcweir { 1222*cdf0e10cSrcweir // when a transformation is set, embed to it 1223*cdf0e10cSrcweir const drawinglayer::primitive2d::Primitive2DReference xPrim(pBitmapWallpaperFill); 1224*cdf0e10cSrcweir 1225*cdf0e10cSrcweir rTarget.append( 1226*cdf0e10cSrcweir new drawinglayer::primitive2d::TransformPrimitive2D( 1227*cdf0e10cSrcweir rProperty.getTransformation(), 1228*cdf0e10cSrcweir drawinglayer::primitive2d::Primitive2DSequence(&xPrim, 1))); 1229*cdf0e10cSrcweir } 1230*cdf0e10cSrcweir } 1231*cdf0e10cSrcweir 1232*cdf0e10cSrcweir /** helper to decide UnderlineAbove for text primitives */ 1233*cdf0e10cSrcweir bool isUnderlineAbove(const Font& rFont) 1234*cdf0e10cSrcweir { 1235*cdf0e10cSrcweir if(!rFont.IsVertical()) 1236*cdf0e10cSrcweir { 1237*cdf0e10cSrcweir return false; 1238*cdf0e10cSrcweir } 1239*cdf0e10cSrcweir 1240*cdf0e10cSrcweir if((LANGUAGE_JAPANESE == rFont.GetLanguage()) || (LANGUAGE_JAPANESE == rFont.GetCJKContextLanguage())) 1241*cdf0e10cSrcweir { 1242*cdf0e10cSrcweir // the underline is right for Japanese only 1243*cdf0e10cSrcweir return true; 1244*cdf0e10cSrcweir } 1245*cdf0e10cSrcweir 1246*cdf0e10cSrcweir return false; 1247*cdf0e10cSrcweir } 1248*cdf0e10cSrcweir 1249*cdf0e10cSrcweir void createFontAttributeTransformAndAlignment( 1250*cdf0e10cSrcweir drawinglayer::attribute::FontAttribute& rFontAttribute, 1251*cdf0e10cSrcweir basegfx::B2DHomMatrix& rTextTransform, 1252*cdf0e10cSrcweir basegfx::B2DVector& rAlignmentOffset, 1253*cdf0e10cSrcweir PropertyHolder& rProperty) 1254*cdf0e10cSrcweir { 1255*cdf0e10cSrcweir const Font& rFont = rProperty.getFont(); 1256*cdf0e10cSrcweir basegfx::B2DVector aFontScaling; 1257*cdf0e10cSrcweir 1258*cdf0e10cSrcweir rFontAttribute = drawinglayer::attribute::FontAttribute( 1259*cdf0e10cSrcweir drawinglayer::primitive2d::getFontAttributeFromVclFont( 1260*cdf0e10cSrcweir aFontScaling, 1261*cdf0e10cSrcweir rFont, 1262*cdf0e10cSrcweir 0 != (rProperty.getLayoutMode() & TEXT_LAYOUT_BIDI_RTL), 1263*cdf0e10cSrcweir 0 != (rProperty.getLayoutMode() & TEXT_LAYOUT_BIDI_STRONG))); 1264*cdf0e10cSrcweir 1265*cdf0e10cSrcweir // add FontScaling 1266*cdf0e10cSrcweir rTextTransform.scale(aFontScaling.getX(), aFontScaling.getY()); 1267*cdf0e10cSrcweir 1268*cdf0e10cSrcweir // take text align into account 1269*cdf0e10cSrcweir if(ALIGN_BASELINE != rFont.GetAlign()) 1270*cdf0e10cSrcweir { 1271*cdf0e10cSrcweir drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice; 1272*cdf0e10cSrcweir aTextLayouterDevice.setFont(rFont); 1273*cdf0e10cSrcweir 1274*cdf0e10cSrcweir if(ALIGN_TOP == rFont.GetAlign()) 1275*cdf0e10cSrcweir { 1276*cdf0e10cSrcweir rAlignmentOffset.setY(aTextLayouterDevice.getFontAscent()); 1277*cdf0e10cSrcweir } 1278*cdf0e10cSrcweir else // ALIGN_BOTTOM 1279*cdf0e10cSrcweir { 1280*cdf0e10cSrcweir rAlignmentOffset.setY(-aTextLayouterDevice.getFontDescent()); 1281*cdf0e10cSrcweir } 1282*cdf0e10cSrcweir 1283*cdf0e10cSrcweir rTextTransform.translate(rAlignmentOffset.getX(), rAlignmentOffset.getY()); 1284*cdf0e10cSrcweir } 1285*cdf0e10cSrcweir 1286*cdf0e10cSrcweir // add FontRotation (if used) 1287*cdf0e10cSrcweir if(rFont.GetOrientation()) 1288*cdf0e10cSrcweir { 1289*cdf0e10cSrcweir rTextTransform.rotate(-rFont.GetOrientation() * F_PI1800); 1290*cdf0e10cSrcweir } 1291*cdf0e10cSrcweir } 1292*cdf0e10cSrcweir 1293*cdf0e10cSrcweir /** helper which takes complete care for creating the needed text primitives. It 1294*cdf0e10cSrcweir takes care of decorated stuff and all the geometry adaptions needed 1295*cdf0e10cSrcweir */ 1296*cdf0e10cSrcweir void proccessMetaTextAction( 1297*cdf0e10cSrcweir const Point& rTextStartPosition, 1298*cdf0e10cSrcweir const XubString& rText, 1299*cdf0e10cSrcweir sal_uInt16 nTextStart, 1300*cdf0e10cSrcweir sal_uInt16 nTextLength, 1301*cdf0e10cSrcweir const ::std::vector< double >& rDXArray, 1302*cdf0e10cSrcweir TargetHolder& rTarget, 1303*cdf0e10cSrcweir PropertyHolder& rProperty) 1304*cdf0e10cSrcweir { 1305*cdf0e10cSrcweir drawinglayer::primitive2d::BasePrimitive2D* pResult = 0; 1306*cdf0e10cSrcweir const Font& rFont = rProperty.getFont(); 1307*cdf0e10cSrcweir basegfx::B2DVector aAlignmentOffset(0.0, 0.0); 1308*cdf0e10cSrcweir 1309*cdf0e10cSrcweir if(nTextLength) 1310*cdf0e10cSrcweir { 1311*cdf0e10cSrcweir drawinglayer::attribute::FontAttribute aFontAttribute; 1312*cdf0e10cSrcweir basegfx::B2DHomMatrix aTextTransform; 1313*cdf0e10cSrcweir 1314*cdf0e10cSrcweir // fill parameters derived from current font 1315*cdf0e10cSrcweir createFontAttributeTransformAndAlignment( 1316*cdf0e10cSrcweir aFontAttribute, 1317*cdf0e10cSrcweir aTextTransform, 1318*cdf0e10cSrcweir aAlignmentOffset, 1319*cdf0e10cSrcweir rProperty); 1320*cdf0e10cSrcweir 1321*cdf0e10cSrcweir // add TextStartPosition 1322*cdf0e10cSrcweir aTextTransform.translate(rTextStartPosition.X(), rTextStartPosition.Y()); 1323*cdf0e10cSrcweir 1324*cdf0e10cSrcweir // prepare FontColor and Locale 1325*cdf0e10cSrcweir const basegfx::BColor aFontColor(rProperty.getTextColor()); 1326*cdf0e10cSrcweir const com::sun::star::lang::Locale aLocale(MsLangId::convertLanguageToLocale(rProperty.getLanguageType())); 1327*cdf0e10cSrcweir const bool bWordLineMode(rFont.IsWordLineMode()); 1328*cdf0e10cSrcweir 1329*cdf0e10cSrcweir const bool bDecoratedIsNeeded( 1330*cdf0e10cSrcweir UNDERLINE_NONE != rFont.GetOverline() 1331*cdf0e10cSrcweir || UNDERLINE_NONE != rFont.GetUnderline() 1332*cdf0e10cSrcweir || STRIKEOUT_NONE != rFont.GetStrikeout() 1333*cdf0e10cSrcweir || EMPHASISMARK_NONE != (rFont.GetEmphasisMark() & EMPHASISMARK_STYLE) 1334*cdf0e10cSrcweir || RELIEF_NONE != rFont.GetRelief() 1335*cdf0e10cSrcweir || rFont.IsShadow() 1336*cdf0e10cSrcweir || bWordLineMode); 1337*cdf0e10cSrcweir 1338*cdf0e10cSrcweir if(bDecoratedIsNeeded) 1339*cdf0e10cSrcweir { 1340*cdf0e10cSrcweir // prepare overline, underline and srikeout data 1341*cdf0e10cSrcweir const drawinglayer::primitive2d::TextLine eFontOverline(drawinglayer::primitive2d::mapFontUnderlineToTextLine(rFont.GetOverline())); 1342*cdf0e10cSrcweir const drawinglayer::primitive2d::TextLine eFontUnderline(drawinglayer::primitive2d::mapFontUnderlineToTextLine(rFont.GetUnderline())); 1343*cdf0e10cSrcweir const drawinglayer::primitive2d::TextStrikeout eTextStrikeout(drawinglayer::primitive2d::mapFontStrikeoutToTextStrikeout(rFont.GetStrikeout())); 1344*cdf0e10cSrcweir 1345*cdf0e10cSrcweir // check UndelineAbove 1346*cdf0e10cSrcweir const bool bUnderlineAbove(drawinglayer::primitive2d::TEXT_LINE_NONE != eFontUnderline && isUnderlineAbove(rFont)); 1347*cdf0e10cSrcweir 1348*cdf0e10cSrcweir // prepare emphasis mark data 1349*cdf0e10cSrcweir drawinglayer::primitive2d::TextEmphasisMark eTextEmphasisMark(drawinglayer::primitive2d::TEXT_EMPHASISMARK_NONE); 1350*cdf0e10cSrcweir 1351*cdf0e10cSrcweir switch(rFont.GetEmphasisMark() & EMPHASISMARK_STYLE) 1352*cdf0e10cSrcweir { 1353*cdf0e10cSrcweir case EMPHASISMARK_DOT : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_EMPHASISMARK_DOT; break; 1354*cdf0e10cSrcweir case EMPHASISMARK_CIRCLE : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_EMPHASISMARK_CIRCLE; break; 1355*cdf0e10cSrcweir case EMPHASISMARK_DISC : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_EMPHASISMARK_DISC; break; 1356*cdf0e10cSrcweir case EMPHASISMARK_ACCENT : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_EMPHASISMARK_ACCENT; break; 1357*cdf0e10cSrcweir } 1358*cdf0e10cSrcweir 1359*cdf0e10cSrcweir const bool bEmphasisMarkAbove(rFont.GetEmphasisMark() & EMPHASISMARK_POS_ABOVE); 1360*cdf0e10cSrcweir const bool bEmphasisMarkBelow(rFont.GetEmphasisMark() & EMPHASISMARK_POS_BELOW); 1361*cdf0e10cSrcweir 1362*cdf0e10cSrcweir // prepare font relief data 1363*cdf0e10cSrcweir drawinglayer::primitive2d::TextRelief eTextRelief(drawinglayer::primitive2d::TEXT_RELIEF_NONE); 1364*cdf0e10cSrcweir 1365*cdf0e10cSrcweir switch(rFont.GetRelief()) 1366*cdf0e10cSrcweir { 1367*cdf0e10cSrcweir case RELIEF_EMBOSSED : eTextRelief = drawinglayer::primitive2d::TEXT_RELIEF_EMBOSSED; break; 1368*cdf0e10cSrcweir case RELIEF_ENGRAVED : eTextRelief = drawinglayer::primitive2d::TEXT_RELIEF_ENGRAVED; break; 1369*cdf0e10cSrcweir default : break; // RELIEF_NONE, FontRelief_FORCE_EQUAL_SIZE 1370*cdf0e10cSrcweir } 1371*cdf0e10cSrcweir 1372*cdf0e10cSrcweir // prepare shadow/outline data 1373*cdf0e10cSrcweir const bool bShadow(rFont.IsShadow()); 1374*cdf0e10cSrcweir 1375*cdf0e10cSrcweir // TextDecoratedPortionPrimitive2D is needed, create one 1376*cdf0e10cSrcweir pResult = new drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D( 1377*cdf0e10cSrcweir 1378*cdf0e10cSrcweir // attributes for TextSimplePortionPrimitive2D 1379*cdf0e10cSrcweir aTextTransform, 1380*cdf0e10cSrcweir rText, 1381*cdf0e10cSrcweir nTextStart, 1382*cdf0e10cSrcweir nTextLength, 1383*cdf0e10cSrcweir rDXArray, 1384*cdf0e10cSrcweir aFontAttribute, 1385*cdf0e10cSrcweir aLocale, 1386*cdf0e10cSrcweir aFontColor, 1387*cdf0e10cSrcweir 1388*cdf0e10cSrcweir // attributes for TextDecoratedPortionPrimitive2D 1389*cdf0e10cSrcweir rProperty.getOverlineColorActive() ? rProperty.getOverlineColor() : aFontColor, 1390*cdf0e10cSrcweir rProperty.getTextLineColorActive() ? rProperty.getTextLineColor() : aFontColor, 1391*cdf0e10cSrcweir eFontOverline, 1392*cdf0e10cSrcweir eFontUnderline, 1393*cdf0e10cSrcweir bUnderlineAbove, 1394*cdf0e10cSrcweir eTextStrikeout, 1395*cdf0e10cSrcweir bWordLineMode, 1396*cdf0e10cSrcweir eTextEmphasisMark, 1397*cdf0e10cSrcweir bEmphasisMarkAbove, 1398*cdf0e10cSrcweir bEmphasisMarkBelow, 1399*cdf0e10cSrcweir eTextRelief, 1400*cdf0e10cSrcweir bShadow); 1401*cdf0e10cSrcweir } 1402*cdf0e10cSrcweir else 1403*cdf0e10cSrcweir { 1404*cdf0e10cSrcweir // TextSimplePortionPrimitive2D is enough 1405*cdf0e10cSrcweir pResult = new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( 1406*cdf0e10cSrcweir aTextTransform, 1407*cdf0e10cSrcweir rText, 1408*cdf0e10cSrcweir nTextStart, 1409*cdf0e10cSrcweir nTextLength, 1410*cdf0e10cSrcweir rDXArray, 1411*cdf0e10cSrcweir aFontAttribute, 1412*cdf0e10cSrcweir aLocale, 1413*cdf0e10cSrcweir aFontColor); 1414*cdf0e10cSrcweir } 1415*cdf0e10cSrcweir } 1416*cdf0e10cSrcweir 1417*cdf0e10cSrcweir if(pResult && rProperty.getTextFillColorActive()) 1418*cdf0e10cSrcweir { 1419*cdf0e10cSrcweir // text background is requested, add and encapsulate both to new primitive 1420*cdf0e10cSrcweir drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice; 1421*cdf0e10cSrcweir aTextLayouterDevice.setFont(rFont); 1422*cdf0e10cSrcweir 1423*cdf0e10cSrcweir // get text width 1424*cdf0e10cSrcweir double fTextWidth(0.0); 1425*cdf0e10cSrcweir 1426*cdf0e10cSrcweir if(rDXArray.empty()) 1427*cdf0e10cSrcweir { 1428*cdf0e10cSrcweir fTextWidth = aTextLayouterDevice.getTextWidth(rText, nTextStart, nTextLength); 1429*cdf0e10cSrcweir } 1430*cdf0e10cSrcweir else 1431*cdf0e10cSrcweir { 1432*cdf0e10cSrcweir fTextWidth = rDXArray.back(); 1433*cdf0e10cSrcweir } 1434*cdf0e10cSrcweir 1435*cdf0e10cSrcweir if(basegfx::fTools::more(fTextWidth, 0.0)) 1436*cdf0e10cSrcweir { 1437*cdf0e10cSrcweir // build text range 1438*cdf0e10cSrcweir const basegfx::B2DRange aTextRange( 1439*cdf0e10cSrcweir 0.0, -aTextLayouterDevice.getFontAscent(), 1440*cdf0e10cSrcweir fTextWidth, aTextLayouterDevice.getFontDescent()); 1441*cdf0e10cSrcweir 1442*cdf0e10cSrcweir // create Transform 1443*cdf0e10cSrcweir basegfx::B2DHomMatrix aTextTransform; 1444*cdf0e10cSrcweir 1445*cdf0e10cSrcweir aTextTransform.translate(aAlignmentOffset.getX(), aAlignmentOffset.getY()); 1446*cdf0e10cSrcweir 1447*cdf0e10cSrcweir if(rFont.GetOrientation()) 1448*cdf0e10cSrcweir { 1449*cdf0e10cSrcweir aTextTransform.rotate(-rFont.GetOrientation() * F_PI1800); 1450*cdf0e10cSrcweir } 1451*cdf0e10cSrcweir 1452*cdf0e10cSrcweir aTextTransform.translate(rTextStartPosition.X(), rTextStartPosition.Y()); 1453*cdf0e10cSrcweir 1454*cdf0e10cSrcweir // prepare Primitive2DSequence, put text in foreground 1455*cdf0e10cSrcweir drawinglayer::primitive2d::Primitive2DSequence aSequence(2); 1456*cdf0e10cSrcweir aSequence[1] = drawinglayer::primitive2d::Primitive2DReference(pResult); 1457*cdf0e10cSrcweir 1458*cdf0e10cSrcweir // prepare filled polygon 1459*cdf0e10cSrcweir basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aTextRange)); 1460*cdf0e10cSrcweir aOutline.transform(aTextTransform); 1461*cdf0e10cSrcweir 1462*cdf0e10cSrcweir aSequence[0] = drawinglayer::primitive2d::Primitive2DReference( 1463*cdf0e10cSrcweir new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( 1464*cdf0e10cSrcweir basegfx::B2DPolyPolygon(aOutline), 1465*cdf0e10cSrcweir rProperty.getTextFillColor())); 1466*cdf0e10cSrcweir 1467*cdf0e10cSrcweir // set as group at pResult 1468*cdf0e10cSrcweir pResult = new drawinglayer::primitive2d::GroupPrimitive2D(aSequence); 1469*cdf0e10cSrcweir } 1470*cdf0e10cSrcweir } 1471*cdf0e10cSrcweir 1472*cdf0e10cSrcweir if(pResult) 1473*cdf0e10cSrcweir { 1474*cdf0e10cSrcweir // add created text primitive to target 1475*cdf0e10cSrcweir if(rProperty.getTransformation().isIdentity()) 1476*cdf0e10cSrcweir { 1477*cdf0e10cSrcweir rTarget.append(pResult); 1478*cdf0e10cSrcweir } 1479*cdf0e10cSrcweir else 1480*cdf0e10cSrcweir { 1481*cdf0e10cSrcweir // when a transformation is set, embed to it 1482*cdf0e10cSrcweir const drawinglayer::primitive2d::Primitive2DReference aReference(pResult); 1483*cdf0e10cSrcweir 1484*cdf0e10cSrcweir rTarget.append( 1485*cdf0e10cSrcweir new drawinglayer::primitive2d::TransformPrimitive2D( 1486*cdf0e10cSrcweir rProperty.getTransformation(), 1487*cdf0e10cSrcweir drawinglayer::primitive2d::Primitive2DSequence(&aReference, 1))); 1488*cdf0e10cSrcweir } 1489*cdf0e10cSrcweir } 1490*cdf0e10cSrcweir } 1491*cdf0e10cSrcweir 1492*cdf0e10cSrcweir /** helper which takes complete care for creating the needed textLine primitives */ 1493*cdf0e10cSrcweir void proccessMetaTextLineAction( 1494*cdf0e10cSrcweir const MetaTextLineAction& rAction, 1495*cdf0e10cSrcweir TargetHolder& rTarget, 1496*cdf0e10cSrcweir PropertyHolder& rProperty) 1497*cdf0e10cSrcweir { 1498*cdf0e10cSrcweir const double fLineWidth(fabs((double)rAction.GetWidth())); 1499*cdf0e10cSrcweir 1500*cdf0e10cSrcweir if(fLineWidth > 0.0) 1501*cdf0e10cSrcweir { 1502*cdf0e10cSrcweir const drawinglayer::primitive2d::TextLine aOverlineMode(drawinglayer::primitive2d::mapFontUnderlineToTextLine(rAction.GetOverline())); 1503*cdf0e10cSrcweir const drawinglayer::primitive2d::TextLine aUnderlineMode(drawinglayer::primitive2d::mapFontUnderlineToTextLine(rAction.GetUnderline())); 1504*cdf0e10cSrcweir const drawinglayer::primitive2d::TextStrikeout aTextStrikeout(drawinglayer::primitive2d::mapFontStrikeoutToTextStrikeout(rAction.GetStrikeout())); 1505*cdf0e10cSrcweir 1506*cdf0e10cSrcweir const bool bOverlineUsed(drawinglayer::primitive2d::TEXT_LINE_NONE != aOverlineMode); 1507*cdf0e10cSrcweir const bool bUnderlineUsed(drawinglayer::primitive2d::TEXT_LINE_NONE != aUnderlineMode); 1508*cdf0e10cSrcweir const bool bStrikeoutUsed(drawinglayer::primitive2d::TEXT_STRIKEOUT_NONE != aTextStrikeout); 1509*cdf0e10cSrcweir 1510*cdf0e10cSrcweir if(bUnderlineUsed || bStrikeoutUsed || bOverlineUsed) 1511*cdf0e10cSrcweir { 1512*cdf0e10cSrcweir std::vector< drawinglayer::primitive2d::BasePrimitive2D* > aTargetVector; 1513*cdf0e10cSrcweir basegfx::B2DVector aAlignmentOffset(0.0, 0.0); 1514*cdf0e10cSrcweir drawinglayer::attribute::FontAttribute aFontAttribute; 1515*cdf0e10cSrcweir basegfx::B2DHomMatrix aTextTransform; 1516*cdf0e10cSrcweir 1517*cdf0e10cSrcweir // fill parameters derived from current font 1518*cdf0e10cSrcweir createFontAttributeTransformAndAlignment( 1519*cdf0e10cSrcweir aFontAttribute, 1520*cdf0e10cSrcweir aTextTransform, 1521*cdf0e10cSrcweir aAlignmentOffset, 1522*cdf0e10cSrcweir rProperty); 1523*cdf0e10cSrcweir 1524*cdf0e10cSrcweir // add TextStartPosition 1525*cdf0e10cSrcweir aTextTransform.translate(rAction.GetStartPoint().X(), rAction.GetStartPoint().Y()); 1526*cdf0e10cSrcweir 1527*cdf0e10cSrcweir // prepare TextLayouter (used in most cases) 1528*cdf0e10cSrcweir drawinglayer::primitive2d::TextLayouterDevice aTextLayouter; 1529*cdf0e10cSrcweir aTextLayouter.setFont(rProperty.getFont()); 1530*cdf0e10cSrcweir 1531*cdf0e10cSrcweir if(bOverlineUsed) 1532*cdf0e10cSrcweir { 1533*cdf0e10cSrcweir // create primitive geometry for overline 1534*cdf0e10cSrcweir aTargetVector.push_back( 1535*cdf0e10cSrcweir new drawinglayer::primitive2d::TextLinePrimitive2D( 1536*cdf0e10cSrcweir aTextTransform, 1537*cdf0e10cSrcweir fLineWidth, 1538*cdf0e10cSrcweir aTextLayouter.getOverlineOffset(), 1539*cdf0e10cSrcweir aTextLayouter.getOverlineHeight(), 1540*cdf0e10cSrcweir aOverlineMode, 1541*cdf0e10cSrcweir rProperty.getOverlineColor())); 1542*cdf0e10cSrcweir } 1543*cdf0e10cSrcweir 1544*cdf0e10cSrcweir if(bUnderlineUsed) 1545*cdf0e10cSrcweir { 1546*cdf0e10cSrcweir // create primitive geometry for underline 1547*cdf0e10cSrcweir aTargetVector.push_back( 1548*cdf0e10cSrcweir new drawinglayer::primitive2d::TextLinePrimitive2D( 1549*cdf0e10cSrcweir aTextTransform, 1550*cdf0e10cSrcweir fLineWidth, 1551*cdf0e10cSrcweir aTextLayouter.getUnderlineOffset(), 1552*cdf0e10cSrcweir aTextLayouter.getUnderlineHeight(), 1553*cdf0e10cSrcweir aUnderlineMode, 1554*cdf0e10cSrcweir rProperty.getTextLineColor())); 1555*cdf0e10cSrcweir } 1556*cdf0e10cSrcweir 1557*cdf0e10cSrcweir if(bStrikeoutUsed) 1558*cdf0e10cSrcweir { 1559*cdf0e10cSrcweir // create primitive geometry for strikeout 1560*cdf0e10cSrcweir if(drawinglayer::primitive2d::TEXT_STRIKEOUT_SLASH == aTextStrikeout 1561*cdf0e10cSrcweir || drawinglayer::primitive2d::TEXT_STRIKEOUT_X == aTextStrikeout) 1562*cdf0e10cSrcweir { 1563*cdf0e10cSrcweir // strikeout with character 1564*cdf0e10cSrcweir const sal_Unicode aStrikeoutChar( 1565*cdf0e10cSrcweir drawinglayer::primitive2d::TEXT_STRIKEOUT_SLASH == aTextStrikeout ? '/' : 'X'); 1566*cdf0e10cSrcweir const com::sun::star::lang::Locale aLocale(MsLangId::convertLanguageToLocale( 1567*cdf0e10cSrcweir rProperty.getLanguageType())); 1568*cdf0e10cSrcweir 1569*cdf0e10cSrcweir aTargetVector.push_back( 1570*cdf0e10cSrcweir new drawinglayer::primitive2d::TextCharacterStrikeoutPrimitive2D( 1571*cdf0e10cSrcweir aTextTransform, 1572*cdf0e10cSrcweir fLineWidth, 1573*cdf0e10cSrcweir rProperty.getTextColor(), 1574*cdf0e10cSrcweir aStrikeoutChar, 1575*cdf0e10cSrcweir aFontAttribute, 1576*cdf0e10cSrcweir aLocale)); 1577*cdf0e10cSrcweir } 1578*cdf0e10cSrcweir else 1579*cdf0e10cSrcweir { 1580*cdf0e10cSrcweir // strikeout with geometry 1581*cdf0e10cSrcweir aTargetVector.push_back( 1582*cdf0e10cSrcweir new drawinglayer::primitive2d::TextGeometryStrikeoutPrimitive2D( 1583*cdf0e10cSrcweir aTextTransform, 1584*cdf0e10cSrcweir fLineWidth, 1585*cdf0e10cSrcweir rProperty.getTextColor(), 1586*cdf0e10cSrcweir aTextLayouter.getUnderlineHeight(), 1587*cdf0e10cSrcweir aTextLayouter.getStrikeoutOffset(), 1588*cdf0e10cSrcweir aTextStrikeout)); 1589*cdf0e10cSrcweir } 1590*cdf0e10cSrcweir } 1591*cdf0e10cSrcweir 1592*cdf0e10cSrcweir if(aTargetVector.size()) 1593*cdf0e10cSrcweir { 1594*cdf0e10cSrcweir // add created text primitive to target 1595*cdf0e10cSrcweir if(rProperty.getTransformation().isIdentity()) 1596*cdf0e10cSrcweir { 1597*cdf0e10cSrcweir for(sal_uInt32 a(0); a < aTargetVector.size(); a++) 1598*cdf0e10cSrcweir { 1599*cdf0e10cSrcweir rTarget.append(aTargetVector[a]); 1600*cdf0e10cSrcweir } 1601*cdf0e10cSrcweir } 1602*cdf0e10cSrcweir else 1603*cdf0e10cSrcweir { 1604*cdf0e10cSrcweir // when a transformation is set, embed to it 1605*cdf0e10cSrcweir drawinglayer::primitive2d::Primitive2DSequence xTargets(aTargetVector.size()); 1606*cdf0e10cSrcweir 1607*cdf0e10cSrcweir for(sal_uInt32 a(0); a < aTargetVector.size(); a++) 1608*cdf0e10cSrcweir { 1609*cdf0e10cSrcweir xTargets[a] = drawinglayer::primitive2d::Primitive2DReference(aTargetVector[a]); 1610*cdf0e10cSrcweir } 1611*cdf0e10cSrcweir 1612*cdf0e10cSrcweir rTarget.append( 1613*cdf0e10cSrcweir new drawinglayer::primitive2d::TransformPrimitive2D( 1614*cdf0e10cSrcweir rProperty.getTransformation(), 1615*cdf0e10cSrcweir xTargets)); 1616*cdf0e10cSrcweir } 1617*cdf0e10cSrcweir } 1618*cdf0e10cSrcweir } 1619*cdf0e10cSrcweir } 1620*cdf0e10cSrcweir 1621*cdf0e10cSrcweir } 1622*cdf0e10cSrcweir 1623*cdf0e10cSrcweir /** This is the main interpreter method. It is designed to handle the given Metafile 1624*cdf0e10cSrcweir completely inside the given context and target. It may use and modify the context and 1625*cdf0e10cSrcweir target. This design allows to call itself recursively wich adapted contexts and 1626*cdf0e10cSrcweir targets as e.g. needed for the META_FLOATTRANSPARENT_ACTION where the content is expressed 1627*cdf0e10cSrcweir as a metafile as sub-content. 1628*cdf0e10cSrcweir 1629*cdf0e10cSrcweir This interpreter is as free of VCL functionality as possible. It uses VCL data classes 1630*cdf0e10cSrcweir (else reading the data would not be possible), but e.g. does NOT use a local OutputDevice 1631*cdf0e10cSrcweir as most other MetaFile interpreters/exporters do to hold and work with the current context. 1632*cdf0e10cSrcweir This is necessary to be able to get away from the strong internal VCL-binding. 1633*cdf0e10cSrcweir 1634*cdf0e10cSrcweir It tries to combine e.g. pixel and/or point actions and to stitch together single line primitives 1635*cdf0e10cSrcweir where possible (which is not trivial with the possible line geometry definitions). 1636*cdf0e10cSrcweir 1637*cdf0e10cSrcweir It tries to handle clipping no longer as Regions and spans of Rectangles, but as PolyPolygon 1638*cdf0e10cSrcweir ClipRegions with (where possible) high precision by using the best possible data quality 1639*cdf0e10cSrcweir from the Region. The Region is unavoidable as data container, but nowadays allows the transport 1640*cdf0e10cSrcweir of Polygon-based clip regions. Where this is not used, a Polygon is constructed from the 1641*cdf0e10cSrcweir Region ranges. All primitive clipping uses the MaskPrimitive2D with Polygon-based clipping. 1642*cdf0e10cSrcweir 1643*cdf0e10cSrcweir I have marked the single MetaActions with: 1644*cdf0e10cSrcweir 1645*cdf0e10cSrcweir SIMPLE, DONE: 1646*cdf0e10cSrcweir Simple, e.g nothing to do or value setting in the context 1647*cdf0e10cSrcweir 1648*cdf0e10cSrcweir CHECKED, WORKS WELL: 1649*cdf0e10cSrcweir Thoroughly tested with extra written test code which created a replacement 1650*cdf0e10cSrcweir Metafile just to test this action in various combinations 1651*cdf0e10cSrcweir 1652*cdf0e10cSrcweir NEEDS IMPLEMENTATION: 1653*cdf0e10cSrcweir Not implemented and asserted, but also no usage found, neither in own Metafile 1654*cdf0e10cSrcweir creations, nor in EMF/WMF imports (checked with a whole bunch of critical EMF/WMF 1655*cdf0e10cSrcweir bugdocs) 1656*cdf0e10cSrcweir 1657*cdf0e10cSrcweir For more commens, see the single action implementations. 1658*cdf0e10cSrcweir */ 1659*cdf0e10cSrcweir void interpretMetafile( 1660*cdf0e10cSrcweir const GDIMetaFile& rMetaFile, 1661*cdf0e10cSrcweir TargetHolders& rTargetHolders, 1662*cdf0e10cSrcweir PropertyHolders& rPropertyHolders, 1663*cdf0e10cSrcweir const drawinglayer::geometry::ViewInformation2D& rViewInformation) 1664*cdf0e10cSrcweir { 1665*cdf0e10cSrcweir const sal_uInt32 nCount(rMetaFile.GetActionCount()); 1666*cdf0e10cSrcweir 1667*cdf0e10cSrcweir for(sal_uInt32 nAction(0); nAction < nCount; nAction++) 1668*cdf0e10cSrcweir { 1669*cdf0e10cSrcweir MetaAction* pAction = rMetaFile.GetAction(nAction); 1670*cdf0e10cSrcweir 1671*cdf0e10cSrcweir switch(pAction->GetType()) 1672*cdf0e10cSrcweir { 1673*cdf0e10cSrcweir case META_NULL_ACTION : 1674*cdf0e10cSrcweir { 1675*cdf0e10cSrcweir /** SIMPLE, DONE */ 1676*cdf0e10cSrcweir break; 1677*cdf0e10cSrcweir } 1678*cdf0e10cSrcweir case META_PIXEL_ACTION : 1679*cdf0e10cSrcweir { 1680*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 1681*cdf0e10cSrcweir std::vector< basegfx::B2DPoint > aPositions; 1682*cdf0e10cSrcweir Color aLastColor(COL_BLACK); 1683*cdf0e10cSrcweir 1684*cdf0e10cSrcweir while(META_PIXEL_ACTION == pAction->GetType() && nAction < nCount) 1685*cdf0e10cSrcweir { 1686*cdf0e10cSrcweir const MetaPixelAction* pA = (const MetaPixelAction*)pAction; 1687*cdf0e10cSrcweir 1688*cdf0e10cSrcweir if(pA->GetColor() != aLastColor) 1689*cdf0e10cSrcweir { 1690*cdf0e10cSrcweir if(aPositions.size()) 1691*cdf0e10cSrcweir { 1692*cdf0e10cSrcweir createPointArrayPrimitive(aPositions, rTargetHolders.Current(), rPropertyHolders.Current(), aLastColor.getBColor()); 1693*cdf0e10cSrcweir aPositions.clear(); 1694*cdf0e10cSrcweir } 1695*cdf0e10cSrcweir 1696*cdf0e10cSrcweir aLastColor = pA->GetColor(); 1697*cdf0e10cSrcweir } 1698*cdf0e10cSrcweir 1699*cdf0e10cSrcweir const Point& rPoint = pA->GetPoint(); 1700*cdf0e10cSrcweir aPositions.push_back(basegfx::B2DPoint(rPoint.X(), rPoint.Y())); 1701*cdf0e10cSrcweir nAction++; if(nAction < nCount) pAction = rMetaFile.GetAction(nAction); 1702*cdf0e10cSrcweir } 1703*cdf0e10cSrcweir 1704*cdf0e10cSrcweir nAction--; 1705*cdf0e10cSrcweir 1706*cdf0e10cSrcweir if(aPositions.size()) 1707*cdf0e10cSrcweir { 1708*cdf0e10cSrcweir createPointArrayPrimitive(aPositions, rTargetHolders.Current(), rPropertyHolders.Current(), aLastColor.getBColor()); 1709*cdf0e10cSrcweir } 1710*cdf0e10cSrcweir 1711*cdf0e10cSrcweir break; 1712*cdf0e10cSrcweir } 1713*cdf0e10cSrcweir case META_POINT_ACTION : 1714*cdf0e10cSrcweir { 1715*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 1716*cdf0e10cSrcweir if(rPropertyHolders.Current().getLineColorActive()) 1717*cdf0e10cSrcweir { 1718*cdf0e10cSrcweir std::vector< basegfx::B2DPoint > aPositions; 1719*cdf0e10cSrcweir 1720*cdf0e10cSrcweir while(META_POINT_ACTION == pAction->GetType() && nAction < nCount) 1721*cdf0e10cSrcweir { 1722*cdf0e10cSrcweir const MetaPointAction* pA = (const MetaPointAction*)pAction; 1723*cdf0e10cSrcweir const Point& rPoint = pA->GetPoint(); 1724*cdf0e10cSrcweir aPositions.push_back(basegfx::B2DPoint(rPoint.X(), rPoint.Y())); 1725*cdf0e10cSrcweir nAction++; if(nAction < nCount) pAction = rMetaFile.GetAction(nAction); 1726*cdf0e10cSrcweir } 1727*cdf0e10cSrcweir 1728*cdf0e10cSrcweir nAction--; 1729*cdf0e10cSrcweir 1730*cdf0e10cSrcweir if(aPositions.size()) 1731*cdf0e10cSrcweir { 1732*cdf0e10cSrcweir createPointArrayPrimitive(aPositions, rTargetHolders.Current(), rPropertyHolders.Current(), rPropertyHolders.Current().getLineColor()); 1733*cdf0e10cSrcweir } 1734*cdf0e10cSrcweir } 1735*cdf0e10cSrcweir 1736*cdf0e10cSrcweir break; 1737*cdf0e10cSrcweir } 1738*cdf0e10cSrcweir case META_LINE_ACTION : 1739*cdf0e10cSrcweir { 1740*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 1741*cdf0e10cSrcweir if(rPropertyHolders.Current().getLineColorActive()) 1742*cdf0e10cSrcweir { 1743*cdf0e10cSrcweir basegfx::B2DPolygon aLinePolygon; 1744*cdf0e10cSrcweir LineInfo aLineInfo; 1745*cdf0e10cSrcweir 1746*cdf0e10cSrcweir while(META_LINE_ACTION == pAction->GetType() && nAction < nCount) 1747*cdf0e10cSrcweir { 1748*cdf0e10cSrcweir const MetaLineAction* pA = (const MetaLineAction*)pAction; 1749*cdf0e10cSrcweir const Point& rStartPoint = pA->GetStartPoint(); 1750*cdf0e10cSrcweir const Point& rEndPoint = pA->GetEndPoint(); 1751*cdf0e10cSrcweir const basegfx::B2DPoint aStart(rStartPoint.X(), rStartPoint.Y()); 1752*cdf0e10cSrcweir const basegfx::B2DPoint aEnd(rEndPoint.X(), rEndPoint.Y()); 1753*cdf0e10cSrcweir 1754*cdf0e10cSrcweir if(aLinePolygon.count()) 1755*cdf0e10cSrcweir { 1756*cdf0e10cSrcweir if(pA->GetLineInfo() == aLineInfo 1757*cdf0e10cSrcweir && aStart == aLinePolygon.getB2DPoint(aLinePolygon.count() - 1)) 1758*cdf0e10cSrcweir { 1759*cdf0e10cSrcweir aLinePolygon.append(aEnd); 1760*cdf0e10cSrcweir } 1761*cdf0e10cSrcweir else 1762*cdf0e10cSrcweir { 1763*cdf0e10cSrcweir aLineInfo.SetLineJoin(basegfx::B2DLINEJOIN_NONE); // It were lines; force to NONE 1764*cdf0e10cSrcweir createLinePrimitive(aLinePolygon, aLineInfo, rTargetHolders.Current(), rPropertyHolders.Current()); 1765*cdf0e10cSrcweir aLinePolygon.clear(); 1766*cdf0e10cSrcweir aLineInfo = pA->GetLineInfo(); 1767*cdf0e10cSrcweir aLinePolygon.append(aStart); 1768*cdf0e10cSrcweir aLinePolygon.append(aEnd); 1769*cdf0e10cSrcweir } 1770*cdf0e10cSrcweir } 1771*cdf0e10cSrcweir else 1772*cdf0e10cSrcweir { 1773*cdf0e10cSrcweir aLineInfo = pA->GetLineInfo(); 1774*cdf0e10cSrcweir aLinePolygon.append(aStart); 1775*cdf0e10cSrcweir aLinePolygon.append(aEnd); 1776*cdf0e10cSrcweir } 1777*cdf0e10cSrcweir 1778*cdf0e10cSrcweir nAction++; if(nAction < nCount) pAction = rMetaFile.GetAction(nAction); 1779*cdf0e10cSrcweir } 1780*cdf0e10cSrcweir 1781*cdf0e10cSrcweir nAction--; 1782*cdf0e10cSrcweir 1783*cdf0e10cSrcweir if(aLinePolygon.count()) 1784*cdf0e10cSrcweir { 1785*cdf0e10cSrcweir aLineInfo.SetLineJoin(basegfx::B2DLINEJOIN_NONE); // It were lines; force to NONE 1786*cdf0e10cSrcweir createLinePrimitive(aLinePolygon, aLineInfo, rTargetHolders.Current(), rPropertyHolders.Current()); 1787*cdf0e10cSrcweir } 1788*cdf0e10cSrcweir } 1789*cdf0e10cSrcweir 1790*cdf0e10cSrcweir break; 1791*cdf0e10cSrcweir } 1792*cdf0e10cSrcweir case META_RECT_ACTION : 1793*cdf0e10cSrcweir { 1794*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 1795*cdf0e10cSrcweir if(rPropertyHolders.Current().getLineOrFillActive()) 1796*cdf0e10cSrcweir { 1797*cdf0e10cSrcweir const MetaRectAction* pA = (const MetaRectAction*)pAction; 1798*cdf0e10cSrcweir const Rectangle& rRectangle = pA->GetRect(); 1799*cdf0e10cSrcweir 1800*cdf0e10cSrcweir if(!rRectangle.IsEmpty()) 1801*cdf0e10cSrcweir { 1802*cdf0e10cSrcweir const basegfx::B2DRange aRange(rRectangle.Left(), rRectangle.Top(), rRectangle.Right(), rRectangle.Bottom()); 1803*cdf0e10cSrcweir 1804*cdf0e10cSrcweir if(!aRange.isEmpty()) 1805*cdf0e10cSrcweir { 1806*cdf0e10cSrcweir const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aRange)); 1807*cdf0e10cSrcweir createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current()); 1808*cdf0e10cSrcweir } 1809*cdf0e10cSrcweir } 1810*cdf0e10cSrcweir } 1811*cdf0e10cSrcweir 1812*cdf0e10cSrcweir break; 1813*cdf0e10cSrcweir } 1814*cdf0e10cSrcweir case META_ROUNDRECT_ACTION : 1815*cdf0e10cSrcweir { 1816*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 1817*cdf0e10cSrcweir /** The original OutputDevice::DrawRect paints nothing when nHor or nVer is zero; but just 1818*cdf0e10cSrcweir because the tools::Polygon operator creating the rounding does produce nonsense. I assume 1819*cdf0e10cSrcweir this an error and create an unrounded rectangle in that case (implicit in 1820*cdf0e10cSrcweir createPolygonFromRect) 1821*cdf0e10cSrcweir */ 1822*cdf0e10cSrcweir if(rPropertyHolders.Current().getLineOrFillActive()) 1823*cdf0e10cSrcweir { 1824*cdf0e10cSrcweir const MetaRoundRectAction* pA = (const MetaRoundRectAction*)pAction; 1825*cdf0e10cSrcweir const Rectangle& rRectangle = pA->GetRect(); 1826*cdf0e10cSrcweir 1827*cdf0e10cSrcweir if(!rRectangle.IsEmpty()) 1828*cdf0e10cSrcweir { 1829*cdf0e10cSrcweir const basegfx::B2DRange aRange(rRectangle.Left(), rRectangle.Top(), rRectangle.Right(), rRectangle.Bottom()); 1830*cdf0e10cSrcweir 1831*cdf0e10cSrcweir if(!aRange.isEmpty()) 1832*cdf0e10cSrcweir { 1833*cdf0e10cSrcweir const sal_uInt32 nHor(pA->GetHorzRound()); 1834*cdf0e10cSrcweir const sal_uInt32 nVer(pA->GetVertRound()); 1835*cdf0e10cSrcweir basegfx::B2DPolygon aOutline; 1836*cdf0e10cSrcweir 1837*cdf0e10cSrcweir if(nHor || nVer) 1838*cdf0e10cSrcweir { 1839*cdf0e10cSrcweir double fRadiusX((nHor * 2.0) / (aRange.getWidth() > 0.0 ? aRange.getWidth() : 1.0)); 1840*cdf0e10cSrcweir double fRadiusY((nVer * 2.0) / (aRange.getHeight() > 0.0 ? aRange.getHeight() : 1.0)); 1841*cdf0e10cSrcweir fRadiusX = std::max(0.0, std::min(1.0, fRadiusX)); 1842*cdf0e10cSrcweir fRadiusY = std::max(0.0, std::min(1.0, fRadiusY)); 1843*cdf0e10cSrcweir 1844*cdf0e10cSrcweir aOutline = basegfx::tools::createPolygonFromRect(aRange, fRadiusX, fRadiusY); 1845*cdf0e10cSrcweir } 1846*cdf0e10cSrcweir else 1847*cdf0e10cSrcweir { 1848*cdf0e10cSrcweir aOutline = basegfx::tools::createPolygonFromRect(aRange); 1849*cdf0e10cSrcweir } 1850*cdf0e10cSrcweir 1851*cdf0e10cSrcweir createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current()); 1852*cdf0e10cSrcweir } 1853*cdf0e10cSrcweir } 1854*cdf0e10cSrcweir } 1855*cdf0e10cSrcweir 1856*cdf0e10cSrcweir break; 1857*cdf0e10cSrcweir } 1858*cdf0e10cSrcweir case META_ELLIPSE_ACTION : 1859*cdf0e10cSrcweir { 1860*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 1861*cdf0e10cSrcweir if(rPropertyHolders.Current().getLineOrFillActive()) 1862*cdf0e10cSrcweir { 1863*cdf0e10cSrcweir const MetaEllipseAction* pA = (const MetaEllipseAction*)pAction; 1864*cdf0e10cSrcweir const Rectangle& rRectangle = pA->GetRect(); 1865*cdf0e10cSrcweir 1866*cdf0e10cSrcweir if(!rRectangle.IsEmpty()) 1867*cdf0e10cSrcweir { 1868*cdf0e10cSrcweir const basegfx::B2DRange aRange(rRectangle.Left(), rRectangle.Top(), rRectangle.Right(), rRectangle.Bottom()); 1869*cdf0e10cSrcweir 1870*cdf0e10cSrcweir if(!aRange.isEmpty()) 1871*cdf0e10cSrcweir { 1872*cdf0e10cSrcweir const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromEllipse( 1873*cdf0e10cSrcweir aRange.getCenter(), aRange.getWidth() * 0.5, aRange.getHeight() * 0.5)); 1874*cdf0e10cSrcweir 1875*cdf0e10cSrcweir createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current()); 1876*cdf0e10cSrcweir } 1877*cdf0e10cSrcweir } 1878*cdf0e10cSrcweir } 1879*cdf0e10cSrcweir 1880*cdf0e10cSrcweir break; 1881*cdf0e10cSrcweir } 1882*cdf0e10cSrcweir case META_ARC_ACTION : 1883*cdf0e10cSrcweir { 1884*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 1885*cdf0e10cSrcweir if(rPropertyHolders.Current().getLineColorActive()) 1886*cdf0e10cSrcweir { 1887*cdf0e10cSrcweir const MetaArcAction* pA = (const MetaArcAction*)pAction; 1888*cdf0e10cSrcweir const Polygon aToolsPoly(pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_ARC); 1889*cdf0e10cSrcweir const basegfx::B2DPolygon aOutline(aToolsPoly.getB2DPolygon()); 1890*cdf0e10cSrcweir 1891*cdf0e10cSrcweir createHairlinePrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current()); 1892*cdf0e10cSrcweir } 1893*cdf0e10cSrcweir 1894*cdf0e10cSrcweir break; 1895*cdf0e10cSrcweir } 1896*cdf0e10cSrcweir case META_PIE_ACTION : 1897*cdf0e10cSrcweir { 1898*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 1899*cdf0e10cSrcweir if(rPropertyHolders.Current().getLineOrFillActive()) 1900*cdf0e10cSrcweir { 1901*cdf0e10cSrcweir const MetaPieAction* pA = (const MetaPieAction*)pAction; 1902*cdf0e10cSrcweir const Polygon aToolsPoly(pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_PIE); 1903*cdf0e10cSrcweir const basegfx::B2DPolygon aOutline(aToolsPoly.getB2DPolygon()); 1904*cdf0e10cSrcweir 1905*cdf0e10cSrcweir createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current()); 1906*cdf0e10cSrcweir } 1907*cdf0e10cSrcweir 1908*cdf0e10cSrcweir break; 1909*cdf0e10cSrcweir } 1910*cdf0e10cSrcweir case META_CHORD_ACTION : 1911*cdf0e10cSrcweir { 1912*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 1913*cdf0e10cSrcweir if(rPropertyHolders.Current().getLineOrFillActive()) 1914*cdf0e10cSrcweir { 1915*cdf0e10cSrcweir const MetaChordAction* pA = (const MetaChordAction*)pAction; 1916*cdf0e10cSrcweir const Polygon aToolsPoly(pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_CHORD); 1917*cdf0e10cSrcweir const basegfx::B2DPolygon aOutline(aToolsPoly.getB2DPolygon()); 1918*cdf0e10cSrcweir 1919*cdf0e10cSrcweir createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current()); 1920*cdf0e10cSrcweir } 1921*cdf0e10cSrcweir 1922*cdf0e10cSrcweir break; 1923*cdf0e10cSrcweir } 1924*cdf0e10cSrcweir case META_POLYLINE_ACTION : 1925*cdf0e10cSrcweir { 1926*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 1927*cdf0e10cSrcweir if(rPropertyHolders.Current().getLineColorActive()) 1928*cdf0e10cSrcweir { 1929*cdf0e10cSrcweir const MetaPolyLineAction* pA = (const MetaPolyLineAction*)pAction; 1930*cdf0e10cSrcweir createLinePrimitive(pA->GetPolygon().getB2DPolygon(), pA->GetLineInfo(), rTargetHolders.Current(), rPropertyHolders.Current()); 1931*cdf0e10cSrcweir } 1932*cdf0e10cSrcweir 1933*cdf0e10cSrcweir break; 1934*cdf0e10cSrcweir } 1935*cdf0e10cSrcweir case META_POLYGON_ACTION : 1936*cdf0e10cSrcweir { 1937*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 1938*cdf0e10cSrcweir if(rPropertyHolders.Current().getLineOrFillActive()) 1939*cdf0e10cSrcweir { 1940*cdf0e10cSrcweir const MetaPolygonAction* pA = (const MetaPolygonAction*)pAction; 1941*cdf0e10cSrcweir basegfx::B2DPolygon aOutline(pA->GetPolygon().getB2DPolygon()); 1942*cdf0e10cSrcweir 1943*cdf0e10cSrcweir // the metafile play interprets the polygons from MetaPolygonAction 1944*cdf0e10cSrcweir // always as closed and always paints an edge from last to first point, 1945*cdf0e10cSrcweir // so force to closed here to emulate that 1946*cdf0e10cSrcweir if(aOutline.count() > 1 && !aOutline.isClosed()) 1947*cdf0e10cSrcweir { 1948*cdf0e10cSrcweir aOutline.setClosed(true); 1949*cdf0e10cSrcweir } 1950*cdf0e10cSrcweir 1951*cdf0e10cSrcweir createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current()); 1952*cdf0e10cSrcweir } 1953*cdf0e10cSrcweir 1954*cdf0e10cSrcweir break; 1955*cdf0e10cSrcweir } 1956*cdf0e10cSrcweir case META_POLYPOLYGON_ACTION : 1957*cdf0e10cSrcweir { 1958*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 1959*cdf0e10cSrcweir if(rPropertyHolders.Current().getLineOrFillActive()) 1960*cdf0e10cSrcweir { 1961*cdf0e10cSrcweir const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*)pAction; 1962*cdf0e10cSrcweir basegfx::B2DPolyPolygon aPolyPolygonOutline(pA->GetPolyPolygon().getB2DPolyPolygon()); 1963*cdf0e10cSrcweir 1964*cdf0e10cSrcweir // the metafile play interprets the single polygons from MetaPolyPolygonAction 1965*cdf0e10cSrcweir // always as closed and always paints an edge from last to first point, 1966*cdf0e10cSrcweir // so force to closed here to emulate that 1967*cdf0e10cSrcweir for(sal_uInt32 b(0); b < aPolyPolygonOutline.count(); b++) 1968*cdf0e10cSrcweir { 1969*cdf0e10cSrcweir basegfx::B2DPolygon aPolygonOutline(aPolyPolygonOutline.getB2DPolygon(b)); 1970*cdf0e10cSrcweir 1971*cdf0e10cSrcweir if(aPolygonOutline.count() > 1 && !aPolygonOutline.isClosed()) 1972*cdf0e10cSrcweir { 1973*cdf0e10cSrcweir aPolygonOutline.setClosed(true); 1974*cdf0e10cSrcweir aPolyPolygonOutline.setB2DPolygon(b, aPolygonOutline); 1975*cdf0e10cSrcweir } 1976*cdf0e10cSrcweir } 1977*cdf0e10cSrcweir 1978*cdf0e10cSrcweir createHairlineAndFillPrimitive(aPolyPolygonOutline, rTargetHolders.Current(), rPropertyHolders.Current()); 1979*cdf0e10cSrcweir } 1980*cdf0e10cSrcweir 1981*cdf0e10cSrcweir break; 1982*cdf0e10cSrcweir } 1983*cdf0e10cSrcweir case META_TEXT_ACTION : 1984*cdf0e10cSrcweir { 1985*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 1986*cdf0e10cSrcweir const MetaTextAction* pA = (const MetaTextAction*)pAction; 1987*cdf0e10cSrcweir sal_uInt32 nTextLength(pA->GetLen()); 1988*cdf0e10cSrcweir const sal_uInt32 nTextIndex(pA->GetIndex()); 1989*cdf0e10cSrcweir const sal_uInt32 nStringLength(pA->GetText().Len()); 1990*cdf0e10cSrcweir 1991*cdf0e10cSrcweir if(nTextLength + nTextIndex > nStringLength) 1992*cdf0e10cSrcweir { 1993*cdf0e10cSrcweir nTextLength = nStringLength - nTextIndex; 1994*cdf0e10cSrcweir } 1995*cdf0e10cSrcweir 1996*cdf0e10cSrcweir if(nTextLength && rPropertyHolders.Current().getTextColorActive()) 1997*cdf0e10cSrcweir { 1998*cdf0e10cSrcweir const std::vector< double > aDXArray; 1999*cdf0e10cSrcweir proccessMetaTextAction( 2000*cdf0e10cSrcweir pA->GetPoint(), 2001*cdf0e10cSrcweir pA->GetText(), 2002*cdf0e10cSrcweir nTextIndex, 2003*cdf0e10cSrcweir nTextLength, 2004*cdf0e10cSrcweir aDXArray, 2005*cdf0e10cSrcweir rTargetHolders.Current(), 2006*cdf0e10cSrcweir rPropertyHolders.Current()); 2007*cdf0e10cSrcweir } 2008*cdf0e10cSrcweir 2009*cdf0e10cSrcweir break; 2010*cdf0e10cSrcweir } 2011*cdf0e10cSrcweir case META_TEXTARRAY_ACTION : 2012*cdf0e10cSrcweir { 2013*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2014*cdf0e10cSrcweir const MetaTextArrayAction* pA = (const MetaTextArrayAction*)pAction; 2015*cdf0e10cSrcweir sal_uInt32 nTextLength(pA->GetLen()); 2016*cdf0e10cSrcweir const sal_uInt32 nTextIndex(pA->GetIndex()); 2017*cdf0e10cSrcweir const sal_uInt32 nStringLength(pA->GetText().Len()); 2018*cdf0e10cSrcweir 2019*cdf0e10cSrcweir if(nTextLength + nTextIndex > nStringLength) 2020*cdf0e10cSrcweir { 2021*cdf0e10cSrcweir nTextLength = nTextIndex > nStringLength ? 0 : nStringLength - nTextIndex; 2022*cdf0e10cSrcweir } 2023*cdf0e10cSrcweir 2024*cdf0e10cSrcweir if(nTextLength && rPropertyHolders.Current().getTextColorActive()) 2025*cdf0e10cSrcweir { 2026*cdf0e10cSrcweir // preapare DXArray (if used) 2027*cdf0e10cSrcweir std::vector< double > aDXArray; 2028*cdf0e10cSrcweir sal_Int32* pDXArray = pA->GetDXArray(); 2029*cdf0e10cSrcweir 2030*cdf0e10cSrcweir if(pDXArray) 2031*cdf0e10cSrcweir { 2032*cdf0e10cSrcweir aDXArray.reserve(nTextLength); 2033*cdf0e10cSrcweir 2034*cdf0e10cSrcweir for(sal_uInt32 a(0); a < nTextLength; a++) 2035*cdf0e10cSrcweir { 2036*cdf0e10cSrcweir aDXArray.push_back((double)(*(pDXArray + a))); 2037*cdf0e10cSrcweir } 2038*cdf0e10cSrcweir } 2039*cdf0e10cSrcweir 2040*cdf0e10cSrcweir proccessMetaTextAction( 2041*cdf0e10cSrcweir pA->GetPoint(), 2042*cdf0e10cSrcweir pA->GetText(), 2043*cdf0e10cSrcweir nTextIndex, 2044*cdf0e10cSrcweir nTextLength, 2045*cdf0e10cSrcweir aDXArray, 2046*cdf0e10cSrcweir rTargetHolders.Current(), 2047*cdf0e10cSrcweir rPropertyHolders.Current()); 2048*cdf0e10cSrcweir } 2049*cdf0e10cSrcweir 2050*cdf0e10cSrcweir break; 2051*cdf0e10cSrcweir } 2052*cdf0e10cSrcweir case META_STRETCHTEXT_ACTION : 2053*cdf0e10cSrcweir { 2054*cdf0e10cSrcweir // #i108440# StarMath uses MetaStretchTextAction, thus support is needed. 2055*cdf0e10cSrcweir // It looks as if it pretty never really uses a width different from 2056*cdf0e10cSrcweir // the default text-layout width, but it's not possible to be sure. 2057*cdf0e10cSrcweir // Implemented getting the DXArray and checking for scale at all. If 2058*cdf0e10cSrcweir // scale is more than 3.5% different, scale the DXArray before usage. 2059*cdf0e10cSrcweir // New status: 2060*cdf0e10cSrcweir 2061*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2062*cdf0e10cSrcweir const MetaStretchTextAction* pA = (const MetaStretchTextAction*)pAction; 2063*cdf0e10cSrcweir sal_uInt32 nTextLength(pA->GetLen()); 2064*cdf0e10cSrcweir const sal_uInt32 nTextIndex(pA->GetIndex()); 2065*cdf0e10cSrcweir const sal_uInt32 nStringLength(pA->GetText().Len()); 2066*cdf0e10cSrcweir 2067*cdf0e10cSrcweir if(nTextLength + nTextIndex > nStringLength) 2068*cdf0e10cSrcweir { 2069*cdf0e10cSrcweir nTextLength = nStringLength - nTextIndex; 2070*cdf0e10cSrcweir } 2071*cdf0e10cSrcweir 2072*cdf0e10cSrcweir if(nTextLength && rPropertyHolders.Current().getTextColorActive()) 2073*cdf0e10cSrcweir { 2074*cdf0e10cSrcweir drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice; 2075*cdf0e10cSrcweir aTextLayouterDevice.setFont(rPropertyHolders.Current().getFont()); 2076*cdf0e10cSrcweir 2077*cdf0e10cSrcweir ::std::vector< double > aTextArray( 2078*cdf0e10cSrcweir aTextLayouterDevice.getTextArray( 2079*cdf0e10cSrcweir pA->GetText(), 2080*cdf0e10cSrcweir nTextIndex, 2081*cdf0e10cSrcweir nTextLength)); 2082*cdf0e10cSrcweir 2083*cdf0e10cSrcweir if(!aTextArray.empty()) 2084*cdf0e10cSrcweir { 2085*cdf0e10cSrcweir const double fTextLength(aTextArray.back()); 2086*cdf0e10cSrcweir 2087*cdf0e10cSrcweir if(0.0 != fTextLength && pA->GetWidth()) 2088*cdf0e10cSrcweir { 2089*cdf0e10cSrcweir const double fRelative(pA->GetWidth() / fTextLength); 2090*cdf0e10cSrcweir 2091*cdf0e10cSrcweir if(fabs(fRelative - 1.0) >= 0.035) 2092*cdf0e10cSrcweir { 2093*cdf0e10cSrcweir // when derivation is more than 3,5% from default text size, 2094*cdf0e10cSrcweir // scale the DXArray 2095*cdf0e10cSrcweir for(sal_uInt32 a(0); a < aTextArray.size(); a++) 2096*cdf0e10cSrcweir { 2097*cdf0e10cSrcweir aTextArray[a] *= fRelative; 2098*cdf0e10cSrcweir } 2099*cdf0e10cSrcweir } 2100*cdf0e10cSrcweir } 2101*cdf0e10cSrcweir } 2102*cdf0e10cSrcweir 2103*cdf0e10cSrcweir proccessMetaTextAction( 2104*cdf0e10cSrcweir pA->GetPoint(), 2105*cdf0e10cSrcweir pA->GetText(), 2106*cdf0e10cSrcweir nTextIndex, 2107*cdf0e10cSrcweir nTextLength, 2108*cdf0e10cSrcweir aTextArray, 2109*cdf0e10cSrcweir rTargetHolders.Current(), 2110*cdf0e10cSrcweir rPropertyHolders.Current()); 2111*cdf0e10cSrcweir } 2112*cdf0e10cSrcweir 2113*cdf0e10cSrcweir break; 2114*cdf0e10cSrcweir } 2115*cdf0e10cSrcweir case META_TEXTRECT_ACTION : 2116*cdf0e10cSrcweir { 2117*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2118*cdf0e10cSrcweir // OSL_ENSURE(false, "META_TEXTRECT_ACTION requested (!)"); 2119*cdf0e10cSrcweir const MetaTextRectAction* pA = (const MetaTextRectAction*)pAction; 2120*cdf0e10cSrcweir const Rectangle& rRectangle = pA->GetRect(); 2121*cdf0e10cSrcweir const sal_uInt32 nStringLength(pA->GetText().Len()); 2122*cdf0e10cSrcweir 2123*cdf0e10cSrcweir if(!rRectangle.IsEmpty() && 0 != nStringLength) 2124*cdf0e10cSrcweir { 2125*cdf0e10cSrcweir // The problem with this action is that it describes unlayouted text 2126*cdf0e10cSrcweir // and the layout capabilities are in EditEngine/Outliner in SVX. The 2127*cdf0e10cSrcweir // same problem is true for VCL which internally has implementations 2128*cdf0e10cSrcweir // to layout text in this case. There exists even a call 2129*cdf0e10cSrcweir // OutputDevice::AddTextRectActions(...) to create the needed actions 2130*cdf0e10cSrcweir // as 'sub-content' of a Metafile. Unfortunately i do not have an 2131*cdf0e10cSrcweir // OutputDevice here since this interpreter tries to work without 2132*cdf0e10cSrcweir // VCL AFAP. 2133*cdf0e10cSrcweir // Since AddTextRectActions is the only way as long as we do not have 2134*cdf0e10cSrcweir // a simple text layouter available, i will try to add it to the 2135*cdf0e10cSrcweir // TextLayouterDevice isloation. 2136*cdf0e10cSrcweir drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice; 2137*cdf0e10cSrcweir aTextLayouterDevice.setFont(rPropertyHolders.Current().getFont()); 2138*cdf0e10cSrcweir GDIMetaFile aGDIMetaFile; 2139*cdf0e10cSrcweir 2140*cdf0e10cSrcweir aTextLayouterDevice.addTextRectActions( 2141*cdf0e10cSrcweir rRectangle, pA->GetText(), pA->GetStyle(), aGDIMetaFile); 2142*cdf0e10cSrcweir 2143*cdf0e10cSrcweir if(aGDIMetaFile.GetActionCount()) 2144*cdf0e10cSrcweir { 2145*cdf0e10cSrcweir // cerate sub-content 2146*cdf0e10cSrcweir drawinglayer::primitive2d::Primitive2DSequence xSubContent; 2147*cdf0e10cSrcweir { 2148*cdf0e10cSrcweir rTargetHolders.Push(); 2149*cdf0e10cSrcweir // #i# for sub-Mteafile contents, do start with new, default render state 2150*cdf0e10cSrcweir rPropertyHolders.PushDefault(); 2151*cdf0e10cSrcweir interpretMetafile(aGDIMetaFile, rTargetHolders, rPropertyHolders, rViewInformation); 2152*cdf0e10cSrcweir xSubContent = rTargetHolders.Current().getPrimitive2DSequence(rPropertyHolders.Current()); 2153*cdf0e10cSrcweir rPropertyHolders.Pop(); 2154*cdf0e10cSrcweir rTargetHolders.Pop(); 2155*cdf0e10cSrcweir } 2156*cdf0e10cSrcweir 2157*cdf0e10cSrcweir if(xSubContent.hasElements()) 2158*cdf0e10cSrcweir { 2159*cdf0e10cSrcweir // add with transformation 2160*cdf0e10cSrcweir rTargetHolders.Current().append( 2161*cdf0e10cSrcweir new drawinglayer::primitive2d::TransformPrimitive2D( 2162*cdf0e10cSrcweir rPropertyHolders.Current().getTransformation(), 2163*cdf0e10cSrcweir xSubContent)); 2164*cdf0e10cSrcweir } 2165*cdf0e10cSrcweir } 2166*cdf0e10cSrcweir } 2167*cdf0e10cSrcweir 2168*cdf0e10cSrcweir break; 2169*cdf0e10cSrcweir } 2170*cdf0e10cSrcweir case META_BMP_ACTION : 2171*cdf0e10cSrcweir { 2172*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2173*cdf0e10cSrcweir const MetaBmpAction* pA = (const MetaBmpAction*)pAction; 2174*cdf0e10cSrcweir const BitmapEx aBitmapEx(pA->GetBitmap()); 2175*cdf0e10cSrcweir 2176*cdf0e10cSrcweir createBitmapExPrimitive(aBitmapEx, pA->GetPoint(), rTargetHolders.Current(), rPropertyHolders.Current()); 2177*cdf0e10cSrcweir 2178*cdf0e10cSrcweir break; 2179*cdf0e10cSrcweir } 2180*cdf0e10cSrcweir case META_BMPSCALE_ACTION : 2181*cdf0e10cSrcweir { 2182*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2183*cdf0e10cSrcweir const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*)pAction; 2184*cdf0e10cSrcweir const Bitmap aBitmapEx(pA->GetBitmap()); 2185*cdf0e10cSrcweir 2186*cdf0e10cSrcweir createBitmapExPrimitive(aBitmapEx, pA->GetPoint(), pA->GetSize(), rTargetHolders.Current(), rPropertyHolders.Current()); 2187*cdf0e10cSrcweir 2188*cdf0e10cSrcweir break; 2189*cdf0e10cSrcweir } 2190*cdf0e10cSrcweir case META_BMPSCALEPART_ACTION : 2191*cdf0e10cSrcweir { 2192*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2193*cdf0e10cSrcweir const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*)pAction; 2194*cdf0e10cSrcweir const Bitmap& rBitmap = pA->GetBitmap(); 2195*cdf0e10cSrcweir 2196*cdf0e10cSrcweir if(!rBitmap.IsEmpty()) 2197*cdf0e10cSrcweir { 2198*cdf0e10cSrcweir Bitmap aCroppedBitmap(rBitmap); 2199*cdf0e10cSrcweir const Rectangle aCropRectangle(pA->GetSrcPoint(), pA->GetSrcSize()); 2200*cdf0e10cSrcweir 2201*cdf0e10cSrcweir if(!aCropRectangle.IsEmpty()) 2202*cdf0e10cSrcweir { 2203*cdf0e10cSrcweir aCroppedBitmap.Crop(aCropRectangle); 2204*cdf0e10cSrcweir } 2205*cdf0e10cSrcweir 2206*cdf0e10cSrcweir const BitmapEx aCroppedBitmapEx(aCroppedBitmap); 2207*cdf0e10cSrcweir createBitmapExPrimitive(aCroppedBitmapEx, pA->GetDestPoint(), pA->GetDestSize(), rTargetHolders.Current(), rPropertyHolders.Current()); 2208*cdf0e10cSrcweir } 2209*cdf0e10cSrcweir 2210*cdf0e10cSrcweir break; 2211*cdf0e10cSrcweir } 2212*cdf0e10cSrcweir case META_BMPEX_ACTION : 2213*cdf0e10cSrcweir { 2214*cdf0e10cSrcweir /** CHECKED, WORKS WELL: Simply same as META_BMP_ACTION */ 2215*cdf0e10cSrcweir const MetaBmpExAction* pA = (const MetaBmpExAction*)pAction; 2216*cdf0e10cSrcweir const BitmapEx& rBitmapEx = pA->GetBitmapEx(); 2217*cdf0e10cSrcweir 2218*cdf0e10cSrcweir createBitmapExPrimitive(rBitmapEx, pA->GetPoint(), rTargetHolders.Current(), rPropertyHolders.Current()); 2219*cdf0e10cSrcweir 2220*cdf0e10cSrcweir break; 2221*cdf0e10cSrcweir } 2222*cdf0e10cSrcweir case META_BMPEXSCALE_ACTION : 2223*cdf0e10cSrcweir { 2224*cdf0e10cSrcweir /** CHECKED, WORKS WELL: Simply same as META_BMPSCALE_ACTION */ 2225*cdf0e10cSrcweir const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*)pAction; 2226*cdf0e10cSrcweir const BitmapEx& rBitmapEx = pA->GetBitmapEx(); 2227*cdf0e10cSrcweir 2228*cdf0e10cSrcweir createBitmapExPrimitive(rBitmapEx, pA->GetPoint(), pA->GetSize(), rTargetHolders.Current(), rPropertyHolders.Current()); 2229*cdf0e10cSrcweir 2230*cdf0e10cSrcweir break; 2231*cdf0e10cSrcweir } 2232*cdf0e10cSrcweir case META_BMPEXSCALEPART_ACTION : 2233*cdf0e10cSrcweir { 2234*cdf0e10cSrcweir /** CHECKED, WORKS WELL: Simply same as META_BMPSCALEPART_ACTION */ 2235*cdf0e10cSrcweir const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*)pAction; 2236*cdf0e10cSrcweir const BitmapEx& rBitmapEx = pA->GetBitmapEx(); 2237*cdf0e10cSrcweir 2238*cdf0e10cSrcweir if(!rBitmapEx.IsEmpty()) 2239*cdf0e10cSrcweir { 2240*cdf0e10cSrcweir BitmapEx aCroppedBitmapEx(rBitmapEx); 2241*cdf0e10cSrcweir const Rectangle aCropRectangle(pA->GetSrcPoint(), pA->GetSrcSize()); 2242*cdf0e10cSrcweir 2243*cdf0e10cSrcweir if(!aCropRectangle.IsEmpty()) 2244*cdf0e10cSrcweir { 2245*cdf0e10cSrcweir aCroppedBitmapEx.Crop(aCropRectangle); 2246*cdf0e10cSrcweir } 2247*cdf0e10cSrcweir 2248*cdf0e10cSrcweir createBitmapExPrimitive(aCroppedBitmapEx, pA->GetDestPoint(), pA->GetDestSize(), rTargetHolders.Current(), rPropertyHolders.Current()); 2249*cdf0e10cSrcweir } 2250*cdf0e10cSrcweir 2251*cdf0e10cSrcweir break; 2252*cdf0e10cSrcweir } 2253*cdf0e10cSrcweir case META_MASK_ACTION : 2254*cdf0e10cSrcweir { 2255*cdf0e10cSrcweir /** CHECKED, WORKS WELL: Simply same as META_BMP_ACTION */ 2256*cdf0e10cSrcweir const MetaMaskAction* pA = (const MetaMaskAction*)pAction; 2257*cdf0e10cSrcweir const BitmapEx aBitmapEx(createMaskBmpEx(pA->GetBitmap(), pA->GetColor())); 2258*cdf0e10cSrcweir 2259*cdf0e10cSrcweir createBitmapExPrimitive(aBitmapEx, pA->GetPoint(), rTargetHolders.Current(), rPropertyHolders.Current()); 2260*cdf0e10cSrcweir 2261*cdf0e10cSrcweir break; 2262*cdf0e10cSrcweir } 2263*cdf0e10cSrcweir case META_MASKSCALE_ACTION : 2264*cdf0e10cSrcweir { 2265*cdf0e10cSrcweir /** CHECKED, WORKS WELL: Simply same as META_BMPSCALE_ACTION */ 2266*cdf0e10cSrcweir const MetaMaskScaleAction* pA = (const MetaMaskScaleAction*)pAction; 2267*cdf0e10cSrcweir const BitmapEx aBitmapEx(createMaskBmpEx(pA->GetBitmap(), pA->GetColor())); 2268*cdf0e10cSrcweir 2269*cdf0e10cSrcweir createBitmapExPrimitive(aBitmapEx, pA->GetPoint(), pA->GetSize(), rTargetHolders.Current(), rPropertyHolders.Current()); 2270*cdf0e10cSrcweir 2271*cdf0e10cSrcweir break; 2272*cdf0e10cSrcweir } 2273*cdf0e10cSrcweir case META_MASKSCALEPART_ACTION : 2274*cdf0e10cSrcweir { 2275*cdf0e10cSrcweir /** CHECKED, WORKS WELL: Simply same as META_BMPSCALEPART_ACTION */ 2276*cdf0e10cSrcweir const MetaMaskScalePartAction* pA = (const MetaMaskScalePartAction*)pAction; 2277*cdf0e10cSrcweir const Bitmap& rBitmap = pA->GetBitmap(); 2278*cdf0e10cSrcweir 2279*cdf0e10cSrcweir if(!rBitmap.IsEmpty()) 2280*cdf0e10cSrcweir { 2281*cdf0e10cSrcweir Bitmap aCroppedBitmap(rBitmap); 2282*cdf0e10cSrcweir const Rectangle aCropRectangle(pA->GetSrcPoint(), pA->GetSrcSize()); 2283*cdf0e10cSrcweir 2284*cdf0e10cSrcweir if(!aCropRectangle.IsEmpty()) 2285*cdf0e10cSrcweir { 2286*cdf0e10cSrcweir aCroppedBitmap.Crop(aCropRectangle); 2287*cdf0e10cSrcweir } 2288*cdf0e10cSrcweir 2289*cdf0e10cSrcweir const BitmapEx aCroppedBitmapEx(createMaskBmpEx(aCroppedBitmap, pA->GetColor())); 2290*cdf0e10cSrcweir createBitmapExPrimitive(aCroppedBitmapEx, pA->GetDestPoint(), pA->GetDestSize(), rTargetHolders.Current(), rPropertyHolders.Current()); 2291*cdf0e10cSrcweir } 2292*cdf0e10cSrcweir 2293*cdf0e10cSrcweir break; 2294*cdf0e10cSrcweir } 2295*cdf0e10cSrcweir case META_GRADIENT_ACTION : 2296*cdf0e10cSrcweir { 2297*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2298*cdf0e10cSrcweir const MetaGradientAction* pA = (const MetaGradientAction*)pAction; 2299*cdf0e10cSrcweir const Rectangle& rRectangle = pA->GetRect(); 2300*cdf0e10cSrcweir 2301*cdf0e10cSrcweir if(!rRectangle.IsEmpty()) 2302*cdf0e10cSrcweir { 2303*cdf0e10cSrcweir basegfx::B2DRange aRange(rRectangle.Left(), rRectangle.Top(), rRectangle.Right(), rRectangle.Bottom()); 2304*cdf0e10cSrcweir 2305*cdf0e10cSrcweir if(!aRange.isEmpty()) 2306*cdf0e10cSrcweir { 2307*cdf0e10cSrcweir const Gradient& rGradient = pA->GetGradient(); 2308*cdf0e10cSrcweir const drawinglayer::attribute::FillGradientAttribute aAttribute(createFillGradientAttribute(rGradient)); 2309*cdf0e10cSrcweir basegfx::B2DPolyPolygon aOutline(basegfx::tools::createPolygonFromRect(aRange)); 2310*cdf0e10cSrcweir 2311*cdf0e10cSrcweir if(aAttribute.getStartColor() == aAttribute.getEndColor()) 2312*cdf0e10cSrcweir { 2313*cdf0e10cSrcweir // not really a gradient. Create filled rectangle 2314*cdf0e10cSrcweir createFillPrimitive( 2315*cdf0e10cSrcweir aOutline, 2316*cdf0e10cSrcweir rTargetHolders.Current(), 2317*cdf0e10cSrcweir rPropertyHolders.Current()); 2318*cdf0e10cSrcweir } 2319*cdf0e10cSrcweir else 2320*cdf0e10cSrcweir { 2321*cdf0e10cSrcweir // really a gradient 2322*cdf0e10cSrcweir aRange.transform(rPropertyHolders.Current().getTransformation()); 2323*cdf0e10cSrcweir drawinglayer::primitive2d::Primitive2DSequence xGradient(1); 2324*cdf0e10cSrcweir 2325*cdf0e10cSrcweir if(rPropertyHolders.Current().isRasterOpInvert()) 2326*cdf0e10cSrcweir { 2327*cdf0e10cSrcweir // use a special version of FillGradientPrimitive2D which creates 2328*cdf0e10cSrcweir // non-overlapping geometry on decomposition to makethe old XOR 2329*cdf0e10cSrcweir // paint 'trick' work. 2330*cdf0e10cSrcweir xGradient[0] = drawinglayer::primitive2d::Primitive2DReference( 2331*cdf0e10cSrcweir new drawinglayer::primitive2d::NonOverlappingFillGradientPrimitive2D( 2332*cdf0e10cSrcweir aRange, 2333*cdf0e10cSrcweir aAttribute)); 2334*cdf0e10cSrcweir } 2335*cdf0e10cSrcweir else 2336*cdf0e10cSrcweir { 2337*cdf0e10cSrcweir xGradient[0] = drawinglayer::primitive2d::Primitive2DReference( 2338*cdf0e10cSrcweir new drawinglayer::primitive2d::FillGradientPrimitive2D( 2339*cdf0e10cSrcweir aRange, 2340*cdf0e10cSrcweir aAttribute)); 2341*cdf0e10cSrcweir } 2342*cdf0e10cSrcweir 2343*cdf0e10cSrcweir // #i112300# clip against polygon representing the rectangle from 2344*cdf0e10cSrcweir // the action. This is implicitely done using a temp Clipping in VCL 2345*cdf0e10cSrcweir // when a MetaGradientAction is executed 2346*cdf0e10cSrcweir aOutline.transform(rPropertyHolders.Current().getTransformation()); 2347*cdf0e10cSrcweir rTargetHolders.Current().append( 2348*cdf0e10cSrcweir new drawinglayer::primitive2d::MaskPrimitive2D( 2349*cdf0e10cSrcweir aOutline, 2350*cdf0e10cSrcweir xGradient)); 2351*cdf0e10cSrcweir } 2352*cdf0e10cSrcweir } 2353*cdf0e10cSrcweir } 2354*cdf0e10cSrcweir 2355*cdf0e10cSrcweir break; 2356*cdf0e10cSrcweir } 2357*cdf0e10cSrcweir case META_HATCH_ACTION : 2358*cdf0e10cSrcweir { 2359*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2360*cdf0e10cSrcweir const MetaHatchAction* pA = (const MetaHatchAction*)pAction; 2361*cdf0e10cSrcweir basegfx::B2DPolyPolygon aOutline(pA->GetPolyPolygon().getB2DPolyPolygon()); 2362*cdf0e10cSrcweir 2363*cdf0e10cSrcweir if(aOutline.count()) 2364*cdf0e10cSrcweir { 2365*cdf0e10cSrcweir const Hatch& rHatch = pA->GetHatch(); 2366*cdf0e10cSrcweir const drawinglayer::attribute::FillHatchAttribute aAttribute(createFillHatchAttribute(rHatch)); 2367*cdf0e10cSrcweir 2368*cdf0e10cSrcweir aOutline.transform(rPropertyHolders.Current().getTransformation()); 2369*cdf0e10cSrcweir 2370*cdf0e10cSrcweir const basegfx::B2DRange aObjectRange(aOutline.getB2DRange()); 2371*cdf0e10cSrcweir const drawinglayer::primitive2d::Primitive2DReference aFillHatch( 2372*cdf0e10cSrcweir new drawinglayer::primitive2d::FillHatchPrimitive2D( 2373*cdf0e10cSrcweir aObjectRange, 2374*cdf0e10cSrcweir basegfx::BColor(), 2375*cdf0e10cSrcweir aAttribute)); 2376*cdf0e10cSrcweir 2377*cdf0e10cSrcweir rTargetHolders.Current().append( 2378*cdf0e10cSrcweir new drawinglayer::primitive2d::MaskPrimitive2D( 2379*cdf0e10cSrcweir aOutline, 2380*cdf0e10cSrcweir drawinglayer::primitive2d::Primitive2DSequence(&aFillHatch, 1))); 2381*cdf0e10cSrcweir } 2382*cdf0e10cSrcweir 2383*cdf0e10cSrcweir break; 2384*cdf0e10cSrcweir } 2385*cdf0e10cSrcweir case META_WALLPAPER_ACTION : 2386*cdf0e10cSrcweir { 2387*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2388*cdf0e10cSrcweir const MetaWallpaperAction* pA = (const MetaWallpaperAction*)pAction; 2389*cdf0e10cSrcweir Rectangle aWallpaperRectangle(pA->GetRect()); 2390*cdf0e10cSrcweir 2391*cdf0e10cSrcweir if(!aWallpaperRectangle.IsEmpty()) 2392*cdf0e10cSrcweir { 2393*cdf0e10cSrcweir const Wallpaper& rWallpaper = pA->GetWallpaper(); 2394*cdf0e10cSrcweir const WallpaperStyle eWallpaperStyle(rWallpaper.GetStyle()); 2395*cdf0e10cSrcweir basegfx::B2DRange aWallpaperRange( 2396*cdf0e10cSrcweir aWallpaperRectangle.Left(), aWallpaperRectangle.Top(), 2397*cdf0e10cSrcweir aWallpaperRectangle.Right(), aWallpaperRectangle.Bottom()); 2398*cdf0e10cSrcweir 2399*cdf0e10cSrcweir if(WALLPAPER_NULL != eWallpaperStyle) 2400*cdf0e10cSrcweir { 2401*cdf0e10cSrcweir if(rWallpaper.IsBitmap()) 2402*cdf0e10cSrcweir { 2403*cdf0e10cSrcweir // create bitmap background. Caution: This 2404*cdf0e10cSrcweir // also will create gradient/color background(s) 2405*cdf0e10cSrcweir // when the bitmap is transparent or not tiled 2406*cdf0e10cSrcweir CreateAndAppendBitmapWallpaper( 2407*cdf0e10cSrcweir aWallpaperRange, 2408*cdf0e10cSrcweir rWallpaper, 2409*cdf0e10cSrcweir rTargetHolders.Current(), 2410*cdf0e10cSrcweir rPropertyHolders.Current()); 2411*cdf0e10cSrcweir } 2412*cdf0e10cSrcweir else if(rWallpaper.IsGradient()) 2413*cdf0e10cSrcweir { 2414*cdf0e10cSrcweir // create gradient background 2415*cdf0e10cSrcweir rTargetHolders.Current().append( 2416*cdf0e10cSrcweir CreateGradientWallpaper( 2417*cdf0e10cSrcweir aWallpaperRange, 2418*cdf0e10cSrcweir rWallpaper.GetGradient(), 2419*cdf0e10cSrcweir rPropertyHolders.Current())); 2420*cdf0e10cSrcweir } 2421*cdf0e10cSrcweir else if(!rWallpaper.GetColor().GetTransparency()) 2422*cdf0e10cSrcweir { 2423*cdf0e10cSrcweir // create color background 2424*cdf0e10cSrcweir rTargetHolders.Current().append( 2425*cdf0e10cSrcweir CreateColorWallpaper( 2426*cdf0e10cSrcweir aWallpaperRange, 2427*cdf0e10cSrcweir rWallpaper.GetColor().getBColor(), 2428*cdf0e10cSrcweir rPropertyHolders.Current())); 2429*cdf0e10cSrcweir } 2430*cdf0e10cSrcweir } 2431*cdf0e10cSrcweir } 2432*cdf0e10cSrcweir 2433*cdf0e10cSrcweir break; 2434*cdf0e10cSrcweir } 2435*cdf0e10cSrcweir case META_CLIPREGION_ACTION : 2436*cdf0e10cSrcweir { 2437*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2438*cdf0e10cSrcweir const MetaClipRegionAction* pA = (const MetaClipRegionAction*)pAction; 2439*cdf0e10cSrcweir 2440*cdf0e10cSrcweir if(pA->IsClipping()) 2441*cdf0e10cSrcweir { 2442*cdf0e10cSrcweir // new clipping. Get PolyPolygon and transform with current transformation 2443*cdf0e10cSrcweir basegfx::B2DPolyPolygon aNewClipPolyPolygon(getB2DPolyPolygonFromRegion(pA->GetRegion())); 2444*cdf0e10cSrcweir 2445*cdf0e10cSrcweir aNewClipPolyPolygon.transform(rPropertyHolders.Current().getTransformation()); 2446*cdf0e10cSrcweir HandleNewClipRegion(aNewClipPolyPolygon, rTargetHolders, rPropertyHolders); 2447*cdf0e10cSrcweir } 2448*cdf0e10cSrcweir else 2449*cdf0e10cSrcweir { 2450*cdf0e10cSrcweir // end clipping 2451*cdf0e10cSrcweir const basegfx::B2DPolyPolygon aEmptyPolyPolygon; 2452*cdf0e10cSrcweir 2453*cdf0e10cSrcweir HandleNewClipRegion(aEmptyPolyPolygon, rTargetHolders, rPropertyHolders); 2454*cdf0e10cSrcweir } 2455*cdf0e10cSrcweir 2456*cdf0e10cSrcweir break; 2457*cdf0e10cSrcweir } 2458*cdf0e10cSrcweir case META_ISECTRECTCLIPREGION_ACTION : 2459*cdf0e10cSrcweir { 2460*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2461*cdf0e10cSrcweir const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*)pAction; 2462*cdf0e10cSrcweir const Rectangle& rRectangle = pA->GetRect(); 2463*cdf0e10cSrcweir 2464*cdf0e10cSrcweir if(rRectangle.IsEmpty()) 2465*cdf0e10cSrcweir { 2466*cdf0e10cSrcweir // intersect with empty rectangle will always give empty 2467*cdf0e10cSrcweir // ClipPolyPolygon; start new clipping with empty PolyPolygon 2468*cdf0e10cSrcweir const basegfx::B2DPolyPolygon aEmptyPolyPolygon; 2469*cdf0e10cSrcweir 2470*cdf0e10cSrcweir HandleNewClipRegion(aEmptyPolyPolygon, rTargetHolders, rPropertyHolders); 2471*cdf0e10cSrcweir } 2472*cdf0e10cSrcweir else 2473*cdf0e10cSrcweir { 2474*cdf0e10cSrcweir // create transformed ClipRange 2475*cdf0e10cSrcweir basegfx::B2DRange aClipRange( 2476*cdf0e10cSrcweir rRectangle.Left(), rRectangle.Top(), 2477*cdf0e10cSrcweir rRectangle.Right(), rRectangle.Bottom()); 2478*cdf0e10cSrcweir 2479*cdf0e10cSrcweir aClipRange.transform(rPropertyHolders.Current().getTransformation()); 2480*cdf0e10cSrcweir 2481*cdf0e10cSrcweir if(rPropertyHolders.Current().getClipPolyPolygonActive()) 2482*cdf0e10cSrcweir { 2483*cdf0e10cSrcweir if(0 == rPropertyHolders.Current().getClipPolyPolygon().count()) 2484*cdf0e10cSrcweir { 2485*cdf0e10cSrcweir // nothing to do, empty active clipPolyPolygon will stay 2486*cdf0e10cSrcweir // empty when intersecting 2487*cdf0e10cSrcweir } 2488*cdf0e10cSrcweir else 2489*cdf0e10cSrcweir { 2490*cdf0e10cSrcweir // AND existing region and new ClipRange 2491*cdf0e10cSrcweir const basegfx::B2DPolyPolygon aOriginalPolyPolygon( 2492*cdf0e10cSrcweir rPropertyHolders.Current().getClipPolyPolygon()); 2493*cdf0e10cSrcweir basegfx::B2DPolyPolygon aClippedPolyPolygon; 2494*cdf0e10cSrcweir 2495*cdf0e10cSrcweir if(aOriginalPolyPolygon.count()) 2496*cdf0e10cSrcweir { 2497*cdf0e10cSrcweir aClippedPolyPolygon = basegfx::tools::clipPolyPolygonOnRange( 2498*cdf0e10cSrcweir aOriginalPolyPolygon, 2499*cdf0e10cSrcweir aClipRange, 2500*cdf0e10cSrcweir true, 2501*cdf0e10cSrcweir false); 2502*cdf0e10cSrcweir } 2503*cdf0e10cSrcweir 2504*cdf0e10cSrcweir if(aClippedPolyPolygon != aOriginalPolyPolygon) 2505*cdf0e10cSrcweir { 2506*cdf0e10cSrcweir // start new clipping with intersected region 2507*cdf0e10cSrcweir HandleNewClipRegion( 2508*cdf0e10cSrcweir aClippedPolyPolygon, 2509*cdf0e10cSrcweir rTargetHolders, 2510*cdf0e10cSrcweir rPropertyHolders); 2511*cdf0e10cSrcweir } 2512*cdf0e10cSrcweir } 2513*cdf0e10cSrcweir } 2514*cdf0e10cSrcweir else 2515*cdf0e10cSrcweir { 2516*cdf0e10cSrcweir // start new clipping with ClipRange 2517*cdf0e10cSrcweir const basegfx::B2DPolyPolygon aNewClipPolyPolygon( 2518*cdf0e10cSrcweir basegfx::tools::createPolygonFromRect(aClipRange)); 2519*cdf0e10cSrcweir 2520*cdf0e10cSrcweir HandleNewClipRegion(aNewClipPolyPolygon, rTargetHolders, rPropertyHolders); 2521*cdf0e10cSrcweir } 2522*cdf0e10cSrcweir } 2523*cdf0e10cSrcweir 2524*cdf0e10cSrcweir break; 2525*cdf0e10cSrcweir } 2526*cdf0e10cSrcweir case META_ISECTREGIONCLIPREGION_ACTION : 2527*cdf0e10cSrcweir { 2528*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2529*cdf0e10cSrcweir const MetaISectRegionClipRegionAction* pA = (const MetaISectRegionClipRegionAction*)pAction; 2530*cdf0e10cSrcweir const Region& rNewRegion = pA->GetRegion(); 2531*cdf0e10cSrcweir 2532*cdf0e10cSrcweir if(rNewRegion.IsEmpty()) 2533*cdf0e10cSrcweir { 2534*cdf0e10cSrcweir // intersect with empty region will always give empty 2535*cdf0e10cSrcweir // region; start new clipping with empty PolyPolygon 2536*cdf0e10cSrcweir const basegfx::B2DPolyPolygon aEmptyPolyPolygon; 2537*cdf0e10cSrcweir 2538*cdf0e10cSrcweir HandleNewClipRegion(aEmptyPolyPolygon, rTargetHolders, rPropertyHolders); 2539*cdf0e10cSrcweir } 2540*cdf0e10cSrcweir else 2541*cdf0e10cSrcweir { 2542*cdf0e10cSrcweir // get new ClipPolyPolygon, transform it with current transformation 2543*cdf0e10cSrcweir basegfx::B2DPolyPolygon aNewClipPolyPolygon(getB2DPolyPolygonFromRegion(rNewRegion)); 2544*cdf0e10cSrcweir aNewClipPolyPolygon.transform(rPropertyHolders.Current().getTransformation()); 2545*cdf0e10cSrcweir 2546*cdf0e10cSrcweir if(rPropertyHolders.Current().getClipPolyPolygonActive()) 2547*cdf0e10cSrcweir { 2548*cdf0e10cSrcweir if(0 == rPropertyHolders.Current().getClipPolyPolygon().count()) 2549*cdf0e10cSrcweir { 2550*cdf0e10cSrcweir // nothing to do, empty active clipPolyPolygon will stay empty 2551*cdf0e10cSrcweir // when intersecting with any region 2552*cdf0e10cSrcweir } 2553*cdf0e10cSrcweir else 2554*cdf0e10cSrcweir { 2555*cdf0e10cSrcweir // AND existing and new region 2556*cdf0e10cSrcweir const basegfx::B2DPolyPolygon aOriginalPolyPolygon( 2557*cdf0e10cSrcweir rPropertyHolders.Current().getClipPolyPolygon()); 2558*cdf0e10cSrcweir basegfx::B2DPolyPolygon aClippedPolyPolygon; 2559*cdf0e10cSrcweir 2560*cdf0e10cSrcweir if(aOriginalPolyPolygon.count()) 2561*cdf0e10cSrcweir { 2562*cdf0e10cSrcweir aClippedPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon( 2563*cdf0e10cSrcweir aOriginalPolyPolygon, aNewClipPolyPolygon, true, false); 2564*cdf0e10cSrcweir } 2565*cdf0e10cSrcweir 2566*cdf0e10cSrcweir if(aClippedPolyPolygon != aOriginalPolyPolygon) 2567*cdf0e10cSrcweir { 2568*cdf0e10cSrcweir // start new clipping with intersected ClipPolyPolygon 2569*cdf0e10cSrcweir HandleNewClipRegion(aClippedPolyPolygon, rTargetHolders, rPropertyHolders); 2570*cdf0e10cSrcweir } 2571*cdf0e10cSrcweir } 2572*cdf0e10cSrcweir } 2573*cdf0e10cSrcweir else 2574*cdf0e10cSrcweir { 2575*cdf0e10cSrcweir // start new clipping with new ClipPolyPolygon 2576*cdf0e10cSrcweir HandleNewClipRegion(aNewClipPolyPolygon, rTargetHolders, rPropertyHolders); 2577*cdf0e10cSrcweir } 2578*cdf0e10cSrcweir } 2579*cdf0e10cSrcweir 2580*cdf0e10cSrcweir break; 2581*cdf0e10cSrcweir } 2582*cdf0e10cSrcweir case META_MOVECLIPREGION_ACTION : 2583*cdf0e10cSrcweir { 2584*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2585*cdf0e10cSrcweir const MetaMoveClipRegionAction* pA = (const MetaMoveClipRegionAction*)pAction; 2586*cdf0e10cSrcweir 2587*cdf0e10cSrcweir if(rPropertyHolders.Current().getClipPolyPolygonActive()) 2588*cdf0e10cSrcweir { 2589*cdf0e10cSrcweir if(0 == rPropertyHolders.Current().getClipPolyPolygon().count()) 2590*cdf0e10cSrcweir { 2591*cdf0e10cSrcweir // nothing to do 2592*cdf0e10cSrcweir } 2593*cdf0e10cSrcweir else 2594*cdf0e10cSrcweir { 2595*cdf0e10cSrcweir const sal_Int32 nHor(pA->GetHorzMove()); 2596*cdf0e10cSrcweir const sal_Int32 nVer(pA->GetVertMove()); 2597*cdf0e10cSrcweir 2598*cdf0e10cSrcweir if(0 != nHor || 0 != nVer) 2599*cdf0e10cSrcweir { 2600*cdf0e10cSrcweir // prepare translation, add current transformation 2601*cdf0e10cSrcweir basegfx::B2DVector aVector(pA->GetHorzMove(), pA->GetVertMove()); 2602*cdf0e10cSrcweir aVector *= rPropertyHolders.Current().getTransformation(); 2603*cdf0e10cSrcweir basegfx::B2DHomMatrix aTransform( 2604*cdf0e10cSrcweir basegfx::tools::createTranslateB2DHomMatrix(aVector)); 2605*cdf0e10cSrcweir 2606*cdf0e10cSrcweir // transform existing region 2607*cdf0e10cSrcweir basegfx::B2DPolyPolygon aClipPolyPolygon( 2608*cdf0e10cSrcweir rPropertyHolders.Current().getClipPolyPolygon()); 2609*cdf0e10cSrcweir 2610*cdf0e10cSrcweir aClipPolyPolygon.transform(aTransform); 2611*cdf0e10cSrcweir HandleNewClipRegion(aClipPolyPolygon, rTargetHolders, rPropertyHolders); 2612*cdf0e10cSrcweir } 2613*cdf0e10cSrcweir } 2614*cdf0e10cSrcweir } 2615*cdf0e10cSrcweir 2616*cdf0e10cSrcweir break; 2617*cdf0e10cSrcweir } 2618*cdf0e10cSrcweir case META_LINECOLOR_ACTION : 2619*cdf0e10cSrcweir { 2620*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2621*cdf0e10cSrcweir const MetaLineColorAction* pA = (const MetaLineColorAction*)pAction; 2622*cdf0e10cSrcweir const bool bActive(pA->IsSetting()); 2623*cdf0e10cSrcweir 2624*cdf0e10cSrcweir rPropertyHolders.Current().setLineColorActive(bActive); 2625*cdf0e10cSrcweir if(bActive) 2626*cdf0e10cSrcweir rPropertyHolders.Current().setLineColor(pA->GetColor().getBColor()); 2627*cdf0e10cSrcweir 2628*cdf0e10cSrcweir break; 2629*cdf0e10cSrcweir } 2630*cdf0e10cSrcweir case META_FILLCOLOR_ACTION : 2631*cdf0e10cSrcweir { 2632*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2633*cdf0e10cSrcweir const MetaFillColorAction* pA = (const MetaFillColorAction*)pAction; 2634*cdf0e10cSrcweir const bool bActive(pA->IsSetting()); 2635*cdf0e10cSrcweir 2636*cdf0e10cSrcweir rPropertyHolders.Current().setFillColorActive(bActive); 2637*cdf0e10cSrcweir if(bActive) 2638*cdf0e10cSrcweir rPropertyHolders.Current().setFillColor(pA->GetColor().getBColor()); 2639*cdf0e10cSrcweir 2640*cdf0e10cSrcweir break; 2641*cdf0e10cSrcweir } 2642*cdf0e10cSrcweir case META_TEXTCOLOR_ACTION : 2643*cdf0e10cSrcweir { 2644*cdf0e10cSrcweir /** SIMPLE, DONE */ 2645*cdf0e10cSrcweir const MetaTextColorAction* pA = (const MetaTextColorAction*)pAction; 2646*cdf0e10cSrcweir const bool bActivate(COL_TRANSPARENT != pA->GetColor().GetColor()); 2647*cdf0e10cSrcweir 2648*cdf0e10cSrcweir rPropertyHolders.Current().setTextColorActive(bActivate); 2649*cdf0e10cSrcweir rPropertyHolders.Current().setTextColor(pA->GetColor().getBColor()); 2650*cdf0e10cSrcweir 2651*cdf0e10cSrcweir break; 2652*cdf0e10cSrcweir } 2653*cdf0e10cSrcweir case META_TEXTFILLCOLOR_ACTION : 2654*cdf0e10cSrcweir { 2655*cdf0e10cSrcweir /** SIMPLE, DONE */ 2656*cdf0e10cSrcweir const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*)pAction; 2657*cdf0e10cSrcweir const bool bWithColorArgument(pA->IsSetting()); 2658*cdf0e10cSrcweir 2659*cdf0e10cSrcweir if(bWithColorArgument) 2660*cdf0e10cSrcweir { 2661*cdf0e10cSrcweir // emulate OutputDevice::SetTextFillColor(...) WITH argument 2662*cdf0e10cSrcweir const Color& rFontFillColor = pA->GetColor(); 2663*cdf0e10cSrcweir rPropertyHolders.Current().setTextFillColor(rFontFillColor.getBColor()); 2664*cdf0e10cSrcweir rPropertyHolders.Current().setTextFillColorActive(COL_TRANSPARENT != rFontFillColor.GetColor()); 2665*cdf0e10cSrcweir } 2666*cdf0e10cSrcweir else 2667*cdf0e10cSrcweir { 2668*cdf0e10cSrcweir // emulate SetFillColor() <- NO argument (!) 2669*cdf0e10cSrcweir rPropertyHolders.Current().setTextFillColorActive(false); 2670*cdf0e10cSrcweir } 2671*cdf0e10cSrcweir 2672*cdf0e10cSrcweir break; 2673*cdf0e10cSrcweir } 2674*cdf0e10cSrcweir case META_TEXTALIGN_ACTION : 2675*cdf0e10cSrcweir { 2676*cdf0e10cSrcweir /** SIMPLE, DONE */ 2677*cdf0e10cSrcweir const MetaTextAlignAction* pA = (const MetaTextAlignAction*)pAction; 2678*cdf0e10cSrcweir const TextAlign aNewTextAlign = pA->GetTextAlign(); 2679*cdf0e10cSrcweir 2680*cdf0e10cSrcweir // TextAlign is applied to the current font (as in 2681*cdf0e10cSrcweir // OutputDevice::SetTextAlign which would be used when 2682*cdf0e10cSrcweir // playing the Metafile) 2683*cdf0e10cSrcweir if(rPropertyHolders.Current().getFont().GetAlign() != aNewTextAlign) 2684*cdf0e10cSrcweir { 2685*cdf0e10cSrcweir Font aNewFont(rPropertyHolders.Current().getFont()); 2686*cdf0e10cSrcweir aNewFont.SetAlign(aNewTextAlign); 2687*cdf0e10cSrcweir rPropertyHolders.Current().setFont(aNewFont); 2688*cdf0e10cSrcweir } 2689*cdf0e10cSrcweir 2690*cdf0e10cSrcweir break; 2691*cdf0e10cSrcweir } 2692*cdf0e10cSrcweir case META_MAPMODE_ACTION : 2693*cdf0e10cSrcweir { 2694*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2695*cdf0e10cSrcweir // the most necessary MapMode to be interpreted is MAP_RELATIVE, 2696*cdf0e10cSrcweir // but also the others may occur. Even not yet supported ones 2697*cdf0e10cSrcweir // may need to be added here later 2698*cdf0e10cSrcweir const MetaMapModeAction* pA = (const MetaMapModeAction*)pAction; 2699*cdf0e10cSrcweir const MapMode& rMapMode = pA->GetMapMode(); 2700*cdf0e10cSrcweir basegfx::B2DHomMatrix aMapping; 2701*cdf0e10cSrcweir 2702*cdf0e10cSrcweir if(MAP_RELATIVE == rMapMode.GetMapUnit()) 2703*cdf0e10cSrcweir { 2704*cdf0e10cSrcweir aMapping = getTransformFromMapMode(rMapMode); 2705*cdf0e10cSrcweir } 2706*cdf0e10cSrcweir else 2707*cdf0e10cSrcweir { 2708*cdf0e10cSrcweir switch(rMapMode.GetMapUnit()) 2709*cdf0e10cSrcweir { 2710*cdf0e10cSrcweir case MAP_100TH_MM : 2711*cdf0e10cSrcweir { 2712*cdf0e10cSrcweir if(MAP_TWIP == rPropertyHolders.Current().getMapUnit()) 2713*cdf0e10cSrcweir { 2714*cdf0e10cSrcweir // MAP_TWIP -> MAP_100TH_MM 2715*cdf0e10cSrcweir const double fTwipTo100thMm(127.0 / 72.0); 2716*cdf0e10cSrcweir aMapping.scale(fTwipTo100thMm, fTwipTo100thMm); 2717*cdf0e10cSrcweir } 2718*cdf0e10cSrcweir break; 2719*cdf0e10cSrcweir } 2720*cdf0e10cSrcweir case MAP_TWIP : 2721*cdf0e10cSrcweir { 2722*cdf0e10cSrcweir if(MAP_100TH_MM == rPropertyHolders.Current().getMapUnit()) 2723*cdf0e10cSrcweir { 2724*cdf0e10cSrcweir // MAP_100TH_MM -> MAP_TWIP 2725*cdf0e10cSrcweir const double f100thMmToTwip(72.0 / 127.0); 2726*cdf0e10cSrcweir aMapping.scale(f100thMmToTwip, f100thMmToTwip); 2727*cdf0e10cSrcweir } 2728*cdf0e10cSrcweir break; 2729*cdf0e10cSrcweir } 2730*cdf0e10cSrcweir default : 2731*cdf0e10cSrcweir { 2732*cdf0e10cSrcweir OSL_ENSURE(false, "interpretMetafile: META_MAPMODE_ACTION with unsupported MapUnit (!)"); 2733*cdf0e10cSrcweir break; 2734*cdf0e10cSrcweir } 2735*cdf0e10cSrcweir } 2736*cdf0e10cSrcweir 2737*cdf0e10cSrcweir aMapping = getTransformFromMapMode(rMapMode) * aMapping; 2738*cdf0e10cSrcweir rPropertyHolders.Current().setMapUnit(rMapMode.GetMapUnit()); 2739*cdf0e10cSrcweir } 2740*cdf0e10cSrcweir 2741*cdf0e10cSrcweir if(!aMapping.isIdentity()) 2742*cdf0e10cSrcweir { 2743*cdf0e10cSrcweir aMapping = aMapping * rPropertyHolders.Current().getTransformation(); 2744*cdf0e10cSrcweir rPropertyHolders.Current().setTransformation(aMapping); 2745*cdf0e10cSrcweir } 2746*cdf0e10cSrcweir 2747*cdf0e10cSrcweir break; 2748*cdf0e10cSrcweir } 2749*cdf0e10cSrcweir case META_FONT_ACTION : 2750*cdf0e10cSrcweir { 2751*cdf0e10cSrcweir /** SIMPLE, DONE */ 2752*cdf0e10cSrcweir const MetaFontAction* pA = (const MetaFontAction*)pAction; 2753*cdf0e10cSrcweir rPropertyHolders.Current().setFont(pA->GetFont()); 2754*cdf0e10cSrcweir Size aFontSize(pA->GetFont().GetSize()); 2755*cdf0e10cSrcweir 2756*cdf0e10cSrcweir if(0 == aFontSize.Height()) 2757*cdf0e10cSrcweir { 2758*cdf0e10cSrcweir // this should not happen but i got Metafiles where this was the 2759*cdf0e10cSrcweir // case. A height needs to be guessed (similar to OutputDevice::ImplNewFont()) 2760*cdf0e10cSrcweir Font aCorrectedFont(pA->GetFont()); 2761*cdf0e10cSrcweir 2762*cdf0e10cSrcweir // guess 16 pixel (as in VCL) 2763*cdf0e10cSrcweir aFontSize = Size(0, 16); 2764*cdf0e10cSrcweir 2765*cdf0e10cSrcweir // convert to target MapUnit if not pixels 2766*cdf0e10cSrcweir aFontSize = Application::GetDefaultDevice()->LogicToLogic( 2767*cdf0e10cSrcweir aFontSize, MAP_PIXEL, rPropertyHolders.Current().getMapUnit()); 2768*cdf0e10cSrcweir 2769*cdf0e10cSrcweir aCorrectedFont.SetSize(aFontSize); 2770*cdf0e10cSrcweir rPropertyHolders.Current().setFont(aCorrectedFont); 2771*cdf0e10cSrcweir } 2772*cdf0e10cSrcweir 2773*cdf0e10cSrcweir // older Metafiles have no META_TEXTCOLOR_ACTION which defines 2774*cdf0e10cSrcweir // the FontColor now, so use the Font's color when not transparent 2775*cdf0e10cSrcweir const Color& rFontColor = pA->GetFont().GetColor(); 2776*cdf0e10cSrcweir const bool bActivate(COL_TRANSPARENT != rFontColor.GetColor()); 2777*cdf0e10cSrcweir 2778*cdf0e10cSrcweir if(bActivate) 2779*cdf0e10cSrcweir { 2780*cdf0e10cSrcweir rPropertyHolders.Current().setTextColor(rFontColor.getBColor()); 2781*cdf0e10cSrcweir } 2782*cdf0e10cSrcweir 2783*cdf0e10cSrcweir // caution: do NOT decativate here on transparet, see 2784*cdf0e10cSrcweir // OutputDevice::SetFont(..) for more info 2785*cdf0e10cSrcweir // rPropertyHolders.Current().setTextColorActive(bActivate); 2786*cdf0e10cSrcweir 2787*cdf0e10cSrcweir // for fill color emulate a MetaTextFillColorAction with !transparent as bool, 2788*cdf0e10cSrcweir // see OutputDevice::SetFont(..) the if(mpMetaFile) case 2789*cdf0e10cSrcweir if(bActivate) 2790*cdf0e10cSrcweir { 2791*cdf0e10cSrcweir const Color& rFontFillColor = pA->GetFont().GetFillColor(); 2792*cdf0e10cSrcweir rPropertyHolders.Current().setTextFillColor(rFontFillColor.getBColor()); 2793*cdf0e10cSrcweir rPropertyHolders.Current().setTextFillColorActive(COL_TRANSPARENT != rFontFillColor.GetColor()); 2794*cdf0e10cSrcweir } 2795*cdf0e10cSrcweir else 2796*cdf0e10cSrcweir { 2797*cdf0e10cSrcweir rPropertyHolders.Current().setTextFillColorActive(false); 2798*cdf0e10cSrcweir } 2799*cdf0e10cSrcweir 2800*cdf0e10cSrcweir break; 2801*cdf0e10cSrcweir } 2802*cdf0e10cSrcweir case META_PUSH_ACTION : 2803*cdf0e10cSrcweir { 2804*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2805*cdf0e10cSrcweir const MetaPushAction* pA = (const MetaPushAction*)pAction; 2806*cdf0e10cSrcweir rPropertyHolders.Push(pA->GetFlags()); 2807*cdf0e10cSrcweir 2808*cdf0e10cSrcweir break; 2809*cdf0e10cSrcweir } 2810*cdf0e10cSrcweir case META_POP_ACTION : 2811*cdf0e10cSrcweir { 2812*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2813*cdf0e10cSrcweir const bool bRegionMayChange(rPropertyHolders.Current().getPushFlags() & PUSH_CLIPREGION); 2814*cdf0e10cSrcweir const bool bRasterOpMayChange(rPropertyHolders.Current().getPushFlags() & PUSH_RASTEROP); 2815*cdf0e10cSrcweir 2816*cdf0e10cSrcweir if(bRegionMayChange && rPropertyHolders.Current().getClipPolyPolygonActive()) 2817*cdf0e10cSrcweir { 2818*cdf0e10cSrcweir // end evtl. clipping 2819*cdf0e10cSrcweir const basegfx::B2DPolyPolygon aEmptyPolyPolygon; 2820*cdf0e10cSrcweir 2821*cdf0e10cSrcweir HandleNewClipRegion(aEmptyPolyPolygon, rTargetHolders, rPropertyHolders); 2822*cdf0e10cSrcweir } 2823*cdf0e10cSrcweir 2824*cdf0e10cSrcweir if(bRasterOpMayChange && rPropertyHolders.Current().isRasterOpActive()) 2825*cdf0e10cSrcweir { 2826*cdf0e10cSrcweir // end evtl. RasterOp 2827*cdf0e10cSrcweir HandleNewRasterOp(ROP_OVERPAINT, rTargetHolders, rPropertyHolders); 2828*cdf0e10cSrcweir } 2829*cdf0e10cSrcweir 2830*cdf0e10cSrcweir rPropertyHolders.Pop(); 2831*cdf0e10cSrcweir 2832*cdf0e10cSrcweir if(bRasterOpMayChange && rPropertyHolders.Current().isRasterOpActive()) 2833*cdf0e10cSrcweir { 2834*cdf0e10cSrcweir // start evtl. RasterOp 2835*cdf0e10cSrcweir HandleNewRasterOp(rPropertyHolders.Current().getRasterOp(), rTargetHolders, rPropertyHolders); 2836*cdf0e10cSrcweir } 2837*cdf0e10cSrcweir 2838*cdf0e10cSrcweir if(bRegionMayChange && rPropertyHolders.Current().getClipPolyPolygonActive()) 2839*cdf0e10cSrcweir { 2840*cdf0e10cSrcweir // start evtl. clipping 2841*cdf0e10cSrcweir HandleNewClipRegion( 2842*cdf0e10cSrcweir rPropertyHolders.Current().getClipPolyPolygon(), rTargetHolders, rPropertyHolders); 2843*cdf0e10cSrcweir } 2844*cdf0e10cSrcweir 2845*cdf0e10cSrcweir break; 2846*cdf0e10cSrcweir } 2847*cdf0e10cSrcweir case META_RASTEROP_ACTION : 2848*cdf0e10cSrcweir { 2849*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2850*cdf0e10cSrcweir const MetaRasterOpAction* pA = (const MetaRasterOpAction*)pAction; 2851*cdf0e10cSrcweir const RasterOp aRasterOp = pA->GetRasterOp(); 2852*cdf0e10cSrcweir 2853*cdf0e10cSrcweir HandleNewRasterOp(aRasterOp, rTargetHolders, rPropertyHolders); 2854*cdf0e10cSrcweir 2855*cdf0e10cSrcweir break; 2856*cdf0e10cSrcweir } 2857*cdf0e10cSrcweir case META_TRANSPARENT_ACTION : 2858*cdf0e10cSrcweir { 2859*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2860*cdf0e10cSrcweir const MetaTransparentAction* pA = (const MetaTransparentAction*)pAction; 2861*cdf0e10cSrcweir const basegfx::B2DPolyPolygon aOutline(pA->GetPolyPolygon().getB2DPolyPolygon()); 2862*cdf0e10cSrcweir 2863*cdf0e10cSrcweir if(aOutline.count()) 2864*cdf0e10cSrcweir { 2865*cdf0e10cSrcweir const sal_uInt16 nTransparence(pA->GetTransparence()); 2866*cdf0e10cSrcweir 2867*cdf0e10cSrcweir if(0 == nTransparence) 2868*cdf0e10cSrcweir { 2869*cdf0e10cSrcweir // not transparent 2870*cdf0e10cSrcweir createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current()); 2871*cdf0e10cSrcweir } 2872*cdf0e10cSrcweir else if(nTransparence >= 100) 2873*cdf0e10cSrcweir { 2874*cdf0e10cSrcweir // fully or more than transparent 2875*cdf0e10cSrcweir } 2876*cdf0e10cSrcweir else 2877*cdf0e10cSrcweir { 2878*cdf0e10cSrcweir // transparent. Create new target 2879*cdf0e10cSrcweir rTargetHolders.Push(); 2880*cdf0e10cSrcweir 2881*cdf0e10cSrcweir // create primitives there and get them 2882*cdf0e10cSrcweir createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current()); 2883*cdf0e10cSrcweir const drawinglayer::primitive2d::Primitive2DSequence aSubContent( 2884*cdf0e10cSrcweir rTargetHolders.Current().getPrimitive2DSequence(rPropertyHolders.Current())); 2885*cdf0e10cSrcweir 2886*cdf0e10cSrcweir // back to old target 2887*cdf0e10cSrcweir rTargetHolders.Pop(); 2888*cdf0e10cSrcweir 2889*cdf0e10cSrcweir if(aSubContent.hasElements()) 2890*cdf0e10cSrcweir { 2891*cdf0e10cSrcweir rTargetHolders.Current().append( 2892*cdf0e10cSrcweir new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( 2893*cdf0e10cSrcweir aSubContent, 2894*cdf0e10cSrcweir nTransparence * 0.01)); 2895*cdf0e10cSrcweir } 2896*cdf0e10cSrcweir } 2897*cdf0e10cSrcweir } 2898*cdf0e10cSrcweir 2899*cdf0e10cSrcweir break; 2900*cdf0e10cSrcweir } 2901*cdf0e10cSrcweir case META_EPS_ACTION : 2902*cdf0e10cSrcweir { 2903*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2904*cdf0e10cSrcweir // To support this action, i have added a EpsPrimitive2D which will 2905*cdf0e10cSrcweir // by default decompose to the Metafile replacement data. To support 2906*cdf0e10cSrcweir // this EPS on screen, the renderer visualizing this has to support 2907*cdf0e10cSrcweir // that primitive and visualize the Eps file (e.g. printing) 2908*cdf0e10cSrcweir const MetaEPSAction* pA = (const MetaEPSAction*)pAction; 2909*cdf0e10cSrcweir const Rectangle aRectangle(pA->GetPoint(), pA->GetSize()); 2910*cdf0e10cSrcweir 2911*cdf0e10cSrcweir if(!aRectangle.IsEmpty()) 2912*cdf0e10cSrcweir { 2913*cdf0e10cSrcweir // create object transform 2914*cdf0e10cSrcweir basegfx::B2DHomMatrix aObjectTransform; 2915*cdf0e10cSrcweir 2916*cdf0e10cSrcweir aObjectTransform.set(0, 0, aRectangle.GetWidth()); 2917*cdf0e10cSrcweir aObjectTransform.set(1, 1, aRectangle.GetHeight()); 2918*cdf0e10cSrcweir aObjectTransform.set(0, 2, aRectangle.Left()); 2919*cdf0e10cSrcweir aObjectTransform.set(1, 2, aRectangle.Top()); 2920*cdf0e10cSrcweir 2921*cdf0e10cSrcweir // add current transformation 2922*cdf0e10cSrcweir aObjectTransform = rPropertyHolders.Current().getTransformation() * aObjectTransform; 2923*cdf0e10cSrcweir 2924*cdf0e10cSrcweir // embed using EpsPrimitive 2925*cdf0e10cSrcweir rTargetHolders.Current().append( 2926*cdf0e10cSrcweir new drawinglayer::primitive2d::EpsPrimitive2D( 2927*cdf0e10cSrcweir aObjectTransform, 2928*cdf0e10cSrcweir pA->GetLink(), 2929*cdf0e10cSrcweir pA->GetSubstitute())); 2930*cdf0e10cSrcweir } 2931*cdf0e10cSrcweir 2932*cdf0e10cSrcweir break; 2933*cdf0e10cSrcweir } 2934*cdf0e10cSrcweir case META_REFPOINT_ACTION : 2935*cdf0e10cSrcweir { 2936*cdf0e10cSrcweir /** SIMPLE, DONE */ 2937*cdf0e10cSrcweir // only used for hatch and line pattern offsets, pretty much no longer 2938*cdf0e10cSrcweir // supported today 2939*cdf0e10cSrcweir // const MetaRefPointAction* pA = (const MetaRefPointAction*)pAction; 2940*cdf0e10cSrcweir break; 2941*cdf0e10cSrcweir } 2942*cdf0e10cSrcweir case META_TEXTLINECOLOR_ACTION : 2943*cdf0e10cSrcweir { 2944*cdf0e10cSrcweir /** SIMPLE, DONE */ 2945*cdf0e10cSrcweir const MetaTextLineColorAction* pA = (const MetaTextLineColorAction*)pAction; 2946*cdf0e10cSrcweir const bool bActive(pA->IsSetting()); 2947*cdf0e10cSrcweir 2948*cdf0e10cSrcweir rPropertyHolders.Current().setTextLineColorActive(bActive); 2949*cdf0e10cSrcweir if(bActive) 2950*cdf0e10cSrcweir rPropertyHolders.Current().setTextLineColor(pA->GetColor().getBColor()); 2951*cdf0e10cSrcweir 2952*cdf0e10cSrcweir break; 2953*cdf0e10cSrcweir } 2954*cdf0e10cSrcweir case META_TEXTLINE_ACTION : 2955*cdf0e10cSrcweir { 2956*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2957*cdf0e10cSrcweir // actually creates overline, underline and strikeouts, so 2958*cdf0e10cSrcweir // these should be isolated from TextDecoratedPortionPrimitive2D 2959*cdf0e10cSrcweir // to own primitives. Done, available now. 2960*cdf0e10cSrcweir // 2961*cdf0e10cSrcweir // This Metaaction seems not to be used (was not used in any 2962*cdf0e10cSrcweir // checked files). It's used in combination with the current 2963*cdf0e10cSrcweir // Font. 2964*cdf0e10cSrcweir const MetaTextLineAction* pA = (const MetaTextLineAction*)pAction; 2965*cdf0e10cSrcweir 2966*cdf0e10cSrcweir proccessMetaTextLineAction( 2967*cdf0e10cSrcweir *pA, 2968*cdf0e10cSrcweir rTargetHolders.Current(), 2969*cdf0e10cSrcweir rPropertyHolders.Current()); 2970*cdf0e10cSrcweir 2971*cdf0e10cSrcweir break; 2972*cdf0e10cSrcweir } 2973*cdf0e10cSrcweir case META_FLOATTRANSPARENT_ACTION : 2974*cdf0e10cSrcweir { 2975*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 2976*cdf0e10cSrcweir const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*)pAction; 2977*cdf0e10cSrcweir const Rectangle aTargetRectangle(pA->GetPoint(), pA->GetSize()); 2978*cdf0e10cSrcweir 2979*cdf0e10cSrcweir if(!aTargetRectangle.IsEmpty()) 2980*cdf0e10cSrcweir { 2981*cdf0e10cSrcweir const GDIMetaFile& rContent = pA->GetGDIMetaFile(); 2982*cdf0e10cSrcweir 2983*cdf0e10cSrcweir if(rContent.GetActionCount()) 2984*cdf0e10cSrcweir { 2985*cdf0e10cSrcweir // create the sub-content with no embedding specific to the 2986*cdf0e10cSrcweir // sub-metafile, this seems not to be used. 2987*cdf0e10cSrcweir drawinglayer::primitive2d::Primitive2DSequence xSubContent; 2988*cdf0e10cSrcweir { 2989*cdf0e10cSrcweir rTargetHolders.Push(); 2990*cdf0e10cSrcweir // #i# for sub-Mteafile contents, do start with new, default render state 2991*cdf0e10cSrcweir rPropertyHolders.PushDefault(); 2992*cdf0e10cSrcweir interpretMetafile(rContent, rTargetHolders, rPropertyHolders, rViewInformation); 2993*cdf0e10cSrcweir xSubContent = rTargetHolders.Current().getPrimitive2DSequence(rPropertyHolders.Current()); 2994*cdf0e10cSrcweir rPropertyHolders.Pop(); 2995*cdf0e10cSrcweir rTargetHolders.Pop(); 2996*cdf0e10cSrcweir } 2997*cdf0e10cSrcweir 2998*cdf0e10cSrcweir if(xSubContent.hasElements()) 2999*cdf0e10cSrcweir { 3000*cdf0e10cSrcweir // check if gradient is a real gradient 3001*cdf0e10cSrcweir const Gradient& rGradient = pA->GetGradient(); 3002*cdf0e10cSrcweir const drawinglayer::attribute::FillGradientAttribute aAttribute(createFillGradientAttribute(rGradient)); 3003*cdf0e10cSrcweir 3004*cdf0e10cSrcweir if(aAttribute.getStartColor() == aAttribute.getEndColor()) 3005*cdf0e10cSrcweir { 3006*cdf0e10cSrcweir // not really a gradient; create UnifiedTransparencePrimitive2D 3007*cdf0e10cSrcweir rTargetHolders.Current().append( 3008*cdf0e10cSrcweir new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( 3009*cdf0e10cSrcweir xSubContent, 3010*cdf0e10cSrcweir aAttribute.getStartColor().luminance())); 3011*cdf0e10cSrcweir } 3012*cdf0e10cSrcweir else 3013*cdf0e10cSrcweir { 3014*cdf0e10cSrcweir // really a gradient. Create gradient sub-content (with correct scaling) 3015*cdf0e10cSrcweir basegfx::B2DRange aRange( 3016*cdf0e10cSrcweir aTargetRectangle.Left(), aTargetRectangle.Top(), 3017*cdf0e10cSrcweir aTargetRectangle.Right(), aTargetRectangle.Bottom()); 3018*cdf0e10cSrcweir aRange.transform(rPropertyHolders.Current().getTransformation()); 3019*cdf0e10cSrcweir 3020*cdf0e10cSrcweir // prepare gradient for transparent content 3021*cdf0e10cSrcweir const drawinglayer::primitive2d::Primitive2DReference xTransparence( 3022*cdf0e10cSrcweir new drawinglayer::primitive2d::FillGradientPrimitive2D( 3023*cdf0e10cSrcweir aRange, 3024*cdf0e10cSrcweir aAttribute)); 3025*cdf0e10cSrcweir 3026*cdf0e10cSrcweir // create transparence primitive 3027*cdf0e10cSrcweir rTargetHolders.Current().append( 3028*cdf0e10cSrcweir new drawinglayer::primitive2d::TransparencePrimitive2D( 3029*cdf0e10cSrcweir xSubContent, 3030*cdf0e10cSrcweir drawinglayer::primitive2d::Primitive2DSequence(&xTransparence, 1))); 3031*cdf0e10cSrcweir } 3032*cdf0e10cSrcweir } 3033*cdf0e10cSrcweir } 3034*cdf0e10cSrcweir } 3035*cdf0e10cSrcweir 3036*cdf0e10cSrcweir break; 3037*cdf0e10cSrcweir } 3038*cdf0e10cSrcweir case META_GRADIENTEX_ACTION : 3039*cdf0e10cSrcweir { 3040*cdf0e10cSrcweir /** SIMPLE, DONE */ 3041*cdf0e10cSrcweir // This is only a data holder which is interpreted inside comment actions, 3042*cdf0e10cSrcweir // see META_COMMENT_ACTION for more info 3043*cdf0e10cSrcweir // const MetaGradientExAction* pA = (const MetaGradientExAction*)pAction; 3044*cdf0e10cSrcweir break; 3045*cdf0e10cSrcweir } 3046*cdf0e10cSrcweir case META_LAYOUTMODE_ACTION : 3047*cdf0e10cSrcweir { 3048*cdf0e10cSrcweir /** SIMPLE, DONE */ 3049*cdf0e10cSrcweir const MetaLayoutModeAction* pA = (const MetaLayoutModeAction*)pAction; 3050*cdf0e10cSrcweir rPropertyHolders.Current().setLayoutMode(pA->GetLayoutMode()); 3051*cdf0e10cSrcweir break; 3052*cdf0e10cSrcweir } 3053*cdf0e10cSrcweir case META_TEXTLANGUAGE_ACTION : 3054*cdf0e10cSrcweir { 3055*cdf0e10cSrcweir /** SIMPLE, DONE */ 3056*cdf0e10cSrcweir const MetaTextLanguageAction* pA = (const MetaTextLanguageAction*)pAction; 3057*cdf0e10cSrcweir rPropertyHolders.Current().setLanguageType(pA->GetTextLanguage()); 3058*cdf0e10cSrcweir break; 3059*cdf0e10cSrcweir } 3060*cdf0e10cSrcweir case META_OVERLINECOLOR_ACTION : 3061*cdf0e10cSrcweir { 3062*cdf0e10cSrcweir /** SIMPLE, DONE */ 3063*cdf0e10cSrcweir const MetaOverlineColorAction* pA = (const MetaOverlineColorAction*)pAction; 3064*cdf0e10cSrcweir const bool bActive(pA->IsSetting()); 3065*cdf0e10cSrcweir 3066*cdf0e10cSrcweir rPropertyHolders.Current().setOverlineColorActive(bActive); 3067*cdf0e10cSrcweir if(bActive) 3068*cdf0e10cSrcweir rPropertyHolders.Current().setOverlineColor(pA->GetColor().getBColor()); 3069*cdf0e10cSrcweir 3070*cdf0e10cSrcweir break; 3071*cdf0e10cSrcweir } 3072*cdf0e10cSrcweir case META_RENDERGRAPHIC_ACTION : 3073*cdf0e10cSrcweir { 3074*cdf0e10cSrcweir const MetaRenderGraphicAction* pA = (const MetaRenderGraphicAction*)pAction; 3075*cdf0e10cSrcweir const Rectangle aRectangle(pA->GetPoint(), pA->GetSize()); 3076*cdf0e10cSrcweir 3077*cdf0e10cSrcweir if(!aRectangle.IsEmpty()) 3078*cdf0e10cSrcweir { 3079*cdf0e10cSrcweir // create object transform 3080*cdf0e10cSrcweir basegfx::B2DHomMatrix aObjectTransform; 3081*cdf0e10cSrcweir 3082*cdf0e10cSrcweir aObjectTransform.set(0, 0, aRectangle.GetWidth()); 3083*cdf0e10cSrcweir aObjectTransform.set(1, 1, aRectangle.GetHeight()); 3084*cdf0e10cSrcweir aObjectTransform.set(0, 2, aRectangle.Left()); 3085*cdf0e10cSrcweir aObjectTransform.set(1, 2, aRectangle.Top()); 3086*cdf0e10cSrcweir 3087*cdf0e10cSrcweir // add current transformation 3088*cdf0e10cSrcweir aObjectTransform = rPropertyHolders.Current().getTransformation() * aObjectTransform; 3089*cdf0e10cSrcweir 3090*cdf0e10cSrcweir // embed using EpsPrimitive 3091*cdf0e10cSrcweir rTargetHolders.Current().append( 3092*cdf0e10cSrcweir new drawinglayer::primitive2d::RenderGraphicPrimitive2D( 3093*cdf0e10cSrcweir pA->GetRenderGraphic(), 3094*cdf0e10cSrcweir aObjectTransform ) ); 3095*cdf0e10cSrcweir } 3096*cdf0e10cSrcweir 3097*cdf0e10cSrcweir break; 3098*cdf0e10cSrcweir } 3099*cdf0e10cSrcweir case META_COMMENT_ACTION : 3100*cdf0e10cSrcweir { 3101*cdf0e10cSrcweir /** CHECKED, WORKS WELL */ 3102*cdf0e10cSrcweir // I already implemented 3103*cdf0e10cSrcweir // XPATHFILL_SEQ_BEGIN, XPATHFILL_SEQ_END 3104*cdf0e10cSrcweir // XPATHSTROKE_SEQ_BEGIN, XPATHSTROKE_SEQ_END, 3105*cdf0e10cSrcweir // but opted to remove these again; it works well without them 3106*cdf0e10cSrcweir // and makes the code less dependent from those Metafile Add-Ons 3107*cdf0e10cSrcweir const MetaCommentAction* pA = (const MetaCommentAction*)pAction; 3108*cdf0e10cSrcweir 3109*cdf0e10cSrcweir if(COMPARE_EQUAL == pA->GetComment().CompareIgnoreCaseToAscii("XGRAD_SEQ_BEGIN")) 3110*cdf0e10cSrcweir { 3111*cdf0e10cSrcweir // XGRAD_SEQ_BEGIN, XGRAD_SEQ_END should be supported since the 3112*cdf0e10cSrcweir // pure recorded paint of the gradients uses the XOR paint functionality 3113*cdf0e10cSrcweir // ('trick'). This is (and will be) broblematic with AntAliasing, so it's 3114*cdf0e10cSrcweir // better to use this info 3115*cdf0e10cSrcweir const MetaGradientExAction* pMetaGradientExAction = 0; 3116*cdf0e10cSrcweir bool bDone(false); 3117*cdf0e10cSrcweir sal_uInt32 b(nAction + 1); 3118*cdf0e10cSrcweir 3119*cdf0e10cSrcweir for(; !bDone && b < nCount; b++) 3120*cdf0e10cSrcweir { 3121*cdf0e10cSrcweir pAction = rMetaFile.GetAction(b); 3122*cdf0e10cSrcweir 3123*cdf0e10cSrcweir if(META_GRADIENTEX_ACTION == pAction->GetType()) 3124*cdf0e10cSrcweir { 3125*cdf0e10cSrcweir pMetaGradientExAction = (const MetaGradientExAction*)pAction; 3126*cdf0e10cSrcweir } 3127*cdf0e10cSrcweir else if(META_COMMENT_ACTION == pAction->GetType()) 3128*cdf0e10cSrcweir { 3129*cdf0e10cSrcweir if(COMPARE_EQUAL == ((const MetaCommentAction*)pAction)->GetComment().CompareIgnoreCaseToAscii("XGRAD_SEQ_END")) 3130*cdf0e10cSrcweir { 3131*cdf0e10cSrcweir bDone = true; 3132*cdf0e10cSrcweir } 3133*cdf0e10cSrcweir } 3134*cdf0e10cSrcweir } 3135*cdf0e10cSrcweir 3136*cdf0e10cSrcweir if(bDone && pMetaGradientExAction) 3137*cdf0e10cSrcweir { 3138*cdf0e10cSrcweir // consume actions and skip forward 3139*cdf0e10cSrcweir nAction = b - 1; 3140*cdf0e10cSrcweir 3141*cdf0e10cSrcweir // get geometry data 3142*cdf0e10cSrcweir basegfx::B2DPolyPolygon aPolyPolygon(pMetaGradientExAction->GetPolyPolygon().getB2DPolyPolygon()); 3143*cdf0e10cSrcweir 3144*cdf0e10cSrcweir if(aPolyPolygon.count()) 3145*cdf0e10cSrcweir { 3146*cdf0e10cSrcweir // transform geometry 3147*cdf0e10cSrcweir aPolyPolygon.transform(rPropertyHolders.Current().getTransformation()); 3148*cdf0e10cSrcweir 3149*cdf0e10cSrcweir // get and check if gradient is a real gradient 3150*cdf0e10cSrcweir const Gradient& rGradient = pMetaGradientExAction->GetGradient(); 3151*cdf0e10cSrcweir const drawinglayer::attribute::FillGradientAttribute aAttribute(createFillGradientAttribute(rGradient)); 3152*cdf0e10cSrcweir 3153*cdf0e10cSrcweir if(aAttribute.getStartColor() == aAttribute.getEndColor()) 3154*cdf0e10cSrcweir { 3155*cdf0e10cSrcweir // not really a gradient 3156*cdf0e10cSrcweir rTargetHolders.Current().append( 3157*cdf0e10cSrcweir new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( 3158*cdf0e10cSrcweir aPolyPolygon, 3159*cdf0e10cSrcweir aAttribute.getStartColor())); 3160*cdf0e10cSrcweir } 3161*cdf0e10cSrcweir else 3162*cdf0e10cSrcweir { 3163*cdf0e10cSrcweir // really a gradient 3164*cdf0e10cSrcweir rTargetHolders.Current().append( 3165*cdf0e10cSrcweir new drawinglayer::primitive2d::PolyPolygonGradientPrimitive2D( 3166*cdf0e10cSrcweir aPolyPolygon, 3167*cdf0e10cSrcweir aAttribute)); 3168*cdf0e10cSrcweir } 3169*cdf0e10cSrcweir } 3170*cdf0e10cSrcweir } 3171*cdf0e10cSrcweir } 3172*cdf0e10cSrcweir 3173*cdf0e10cSrcweir break; 3174*cdf0e10cSrcweir } 3175*cdf0e10cSrcweir default: 3176*cdf0e10cSrcweir { 3177*cdf0e10cSrcweir OSL_ENSURE(false, "Unknown MetaFile Action (!)"); 3178*cdf0e10cSrcweir break; 3179*cdf0e10cSrcweir } 3180*cdf0e10cSrcweir } 3181*cdf0e10cSrcweir } 3182*cdf0e10cSrcweir } 3183*cdf0e10cSrcweir } // end of anonymous namespace 3184*cdf0e10cSrcweir 3185*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 3186*cdf0e10cSrcweir 3187*cdf0e10cSrcweir namespace drawinglayer 3188*cdf0e10cSrcweir { 3189*cdf0e10cSrcweir namespace primitive2d 3190*cdf0e10cSrcweir { 3191*cdf0e10cSrcweir Primitive2DSequence MetafilePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const 3192*cdf0e10cSrcweir { 3193*cdf0e10cSrcweir // prepare target and porperties; each will have one default entry 3194*cdf0e10cSrcweir TargetHolders aTargetHolders; 3195*cdf0e10cSrcweir PropertyHolders aPropertyHolders; 3196*cdf0e10cSrcweir 3197*cdf0e10cSrcweir // set target MapUnit at Properties 3198*cdf0e10cSrcweir aPropertyHolders.Current().setMapUnit(getMetaFile().GetPrefMapMode().GetMapUnit()); 3199*cdf0e10cSrcweir 3200*cdf0e10cSrcweir // interpret the Metafile 3201*cdf0e10cSrcweir interpretMetafile(getMetaFile(), aTargetHolders, aPropertyHolders, rViewInformation); 3202*cdf0e10cSrcweir 3203*cdf0e10cSrcweir // get the content. There should be ony one target, as in the start condition, 3204*cdf0e10cSrcweir // but iterating will be the right thing to do when some push/pop is not closed 3205*cdf0e10cSrcweir Primitive2DSequence xRetval; 3206*cdf0e10cSrcweir 3207*cdf0e10cSrcweir while(aTargetHolders.size() > 1) 3208*cdf0e10cSrcweir { 3209*cdf0e10cSrcweir appendPrimitive2DSequenceToPrimitive2DSequence(xRetval, 3210*cdf0e10cSrcweir aTargetHolders.Current().getPrimitive2DSequence(aPropertyHolders.Current())); 3211*cdf0e10cSrcweir aTargetHolders.Pop(); 3212*cdf0e10cSrcweir } 3213*cdf0e10cSrcweir 3214*cdf0e10cSrcweir appendPrimitive2DSequenceToPrimitive2DSequence(xRetval, 3215*cdf0e10cSrcweir aTargetHolders.Current().getPrimitive2DSequence(aPropertyHolders.Current())); 3216*cdf0e10cSrcweir 3217*cdf0e10cSrcweir if(xRetval.hasElements()) 3218*cdf0e10cSrcweir { 3219*cdf0e10cSrcweir // get target size 3220*cdf0e10cSrcweir const Rectangle aMtfTarget(getMetaFile().GetPrefMapMode().GetOrigin(), getMetaFile().GetPrefSize()); 3221*cdf0e10cSrcweir 3222*cdf0e10cSrcweir // create transformation 3223*cdf0e10cSrcweir basegfx::B2DHomMatrix aAdaptedTransform; 3224*cdf0e10cSrcweir 3225*cdf0e10cSrcweir aAdaptedTransform.translate(-aMtfTarget.Left(), -aMtfTarget.Top()); 3226*cdf0e10cSrcweir aAdaptedTransform.scale( 3227*cdf0e10cSrcweir aMtfTarget.getWidth() ? 1.0 / aMtfTarget.getWidth() : 1.0, 3228*cdf0e10cSrcweir aMtfTarget.getHeight() ? 1.0 / aMtfTarget.getHeight() : 1.0); 3229*cdf0e10cSrcweir aAdaptedTransform = getTransform() * aAdaptedTransform; 3230*cdf0e10cSrcweir 3231*cdf0e10cSrcweir // embed to target transformation 3232*cdf0e10cSrcweir const Primitive2DReference aEmbeddedTransform( 3233*cdf0e10cSrcweir new TransformPrimitive2D( 3234*cdf0e10cSrcweir aAdaptedTransform, 3235*cdf0e10cSrcweir xRetval)); 3236*cdf0e10cSrcweir 3237*cdf0e10cSrcweir xRetval = Primitive2DSequence(&aEmbeddedTransform, 1); 3238*cdf0e10cSrcweir } 3239*cdf0e10cSrcweir 3240*cdf0e10cSrcweir return xRetval; 3241*cdf0e10cSrcweir } 3242*cdf0e10cSrcweir 3243*cdf0e10cSrcweir MetafilePrimitive2D::MetafilePrimitive2D( 3244*cdf0e10cSrcweir const basegfx::B2DHomMatrix& rMetaFileTransform, 3245*cdf0e10cSrcweir const GDIMetaFile& rMetaFile) 3246*cdf0e10cSrcweir : BufferedDecompositionPrimitive2D(), 3247*cdf0e10cSrcweir maMetaFileTransform(rMetaFileTransform), 3248*cdf0e10cSrcweir maMetaFile(rMetaFile) 3249*cdf0e10cSrcweir { 3250*cdf0e10cSrcweir } 3251*cdf0e10cSrcweir 3252*cdf0e10cSrcweir bool MetafilePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const 3253*cdf0e10cSrcweir { 3254*cdf0e10cSrcweir if(BufferedDecompositionPrimitive2D::operator==(rPrimitive)) 3255*cdf0e10cSrcweir { 3256*cdf0e10cSrcweir const MetafilePrimitive2D& rCompare = (MetafilePrimitive2D&)rPrimitive; 3257*cdf0e10cSrcweir 3258*cdf0e10cSrcweir return (getTransform() == rCompare.getTransform() 3259*cdf0e10cSrcweir && getMetaFile() == rCompare.getMetaFile()); 3260*cdf0e10cSrcweir } 3261*cdf0e10cSrcweir 3262*cdf0e10cSrcweir return false; 3263*cdf0e10cSrcweir } 3264*cdf0e10cSrcweir 3265*cdf0e10cSrcweir basegfx::B2DRange MetafilePrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const 3266*cdf0e10cSrcweir { 3267*cdf0e10cSrcweir // use own implementation to quickly answer the getB2DRange question. The 3268*cdf0e10cSrcweir // MetafilePrimitive2D assumes that all geometry is inside of the shape. If 3269*cdf0e10cSrcweir // this is not the case (i have already seen some wrong Metafiles) it should 3270*cdf0e10cSrcweir // be embedded to a MaskPrimitive2D 3271*cdf0e10cSrcweir basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); 3272*cdf0e10cSrcweir aRetval.transform(getTransform()); 3273*cdf0e10cSrcweir 3274*cdf0e10cSrcweir return aRetval; 3275*cdf0e10cSrcweir } 3276*cdf0e10cSrcweir 3277*cdf0e10cSrcweir // provide unique ID 3278*cdf0e10cSrcweir ImplPrimitrive2DIDBlock(MetafilePrimitive2D, PRIMITIVE2D_ID_METAFILEPRIMITIVE2D) 3279*cdf0e10cSrcweir 3280*cdf0e10cSrcweir } // end of namespace primitive2d 3281*cdf0e10cSrcweir } // end of namespace drawinglayer 3282*cdf0e10cSrcweir 3283*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 3284*cdf0e10cSrcweir // eof 3285