LCOV - code coverage report
Current view: top level - drawinglayer/source/primitive2d - metafileprimitive2d.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 1179 0.0 %
Date: 2014-04-14 Functions: 0 98 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10