LCOV - code coverage report
Current view: top level - drawinglayer/source/primitive2d - metafileprimitive2d.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 433 1174 36.9 %
Date: 2012-08-25 Functions: 78 98 79.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 420 2532 16.6 %

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

Generated by: LCOV version 1.10