LCOV - code coverage report
Current view: top level - drawinglayer/source/processor2d - vclmetafileprocessor2d.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 452 744 60.8 %
Date: 2014-11-03 Functions: 15 17 88.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "vclmetafileprocessor2d.hxx"
      21             : #include <tools/gen.hxx>
      22             : #include <vcl/virdev.hxx>
      23             : #include <vcl/gdimtf.hxx>
      24             : #include <vcl/gradient.hxx>
      25             : #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
      26             : #include <drawinglayer/primitive2d/textprimitive2d.hxx>
      27             : #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
      28             : #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
      29             : #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
      30             : #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
      31             : #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
      32             : #include <basegfx/polygon/b2dpolygonclipper.hxx>
      33             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      34             : #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
      35             : #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
      36             : #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
      37             : #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
      38             : #include "vclpixelprocessor2d.hxx"
      39             : #include <tools/stream.hxx>
      40             : #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
      41             : #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
      42             : #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
      43             : #include <vcl/graphictools.hxx>
      44             : #include <vcl/metaact.hxx>
      45             : #include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
      46             : #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
      47             : #include <drawinglayer/primitive2d/openglprimitive2d.hxx>
      48             : #include <comphelper/processfactory.hxx>
      49             : #include <rtl/ustring.hxx>
      50             : #include <com/sun/star/i18n/BreakIterator.hpp>
      51             : #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
      52             : #include <com/sun/star/i18n/WordType.hpp>
      53             : #include <drawinglayer/primitive2d/controlprimitive2d.hxx>
      54             : #include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
      55             : #include <basegfx/polygon/b2dpolygontools.hxx>
      56             : #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
      57             : #include <drawinglayer/primitive2d/epsprimitive2d.hxx>
      58             : #include <basegfx/polygon/b2dlinegeometry.hxx>
      59             : #include <vcl/dibtools.hxx>
      60             : 
      61             : // for PDFExtOutDevData Graphic support
      62             : #include <vcl/graph.hxx>
      63             : #include <vcl/svapp.hxx>
      64             : #include <toolkit/helper/formpdfexport.hxx>
      65             : 
      66             : // for Control printing
      67             : #include <com/sun/star/beans/XPropertySet.hpp>
      68             : 
      69             : // for StructureTagPrimitive support in sd's unomodel.cxx
      70             : #include <drawinglayer/primitive2d/structuretagprimitive2d.hxx>
      71             : 
      72             : using namespace com::sun::star;
      73             : 
      74             : // #112245# definition for maximum allowed point count due to Metafile target.
      75             : // To be on the safe side with the old tools polygon, use slightly less then
      76             : // the theoretical maximum (bad experiences with tools polygon)
      77             : 
      78             : #define MAX_POLYGON_POINT_COUNT_METAFILE    (0x0000fff0)
      79             : 
      80             : namespace
      81             : {
      82             :     // #112245# helper to split line polygon in half
      83           0 :     void splitLinePolygon(
      84             :         const basegfx::B2DPolygon& rBasePolygon,
      85             :         basegfx::B2DPolygon& o_aLeft,
      86             :         basegfx::B2DPolygon& o_aRight)
      87             :     {
      88           0 :         const sal_uInt32 nCount(rBasePolygon.count());
      89             : 
      90           0 :         if(nCount)
      91             :         {
      92           0 :             const sal_uInt32 nHalfCount((nCount - 1) >> 1);
      93             : 
      94           0 :             o_aLeft = basegfx::B2DPolygon(rBasePolygon, 0, nHalfCount + 1);
      95           0 :             o_aLeft.setClosed(false);
      96             : 
      97           0 :             o_aRight = basegfx::B2DPolygon(rBasePolygon, nHalfCount, nCount - nHalfCount);
      98           0 :             o_aRight.setClosed(false);
      99             : 
     100           0 :             if(rBasePolygon.isClosed())
     101             :             {
     102           0 :                 o_aRight.append(rBasePolygon.getB2DPoint(0));
     103             : 
     104           0 :                 if(rBasePolygon.areControlPointsUsed())
     105             :                 {
     106             :                     o_aRight.setControlPoints(
     107           0 :                         o_aRight.count() - 1,
     108             :                         rBasePolygon.getPrevControlPoint(0),
     109           0 :                         rBasePolygon.getNextControlPoint(0));
     110             :                 }
     111             :             }
     112             :         }
     113             :         else
     114             :         {
     115           0 :             o_aLeft.clear();
     116           0 :             o_aRight.clear();
     117             :         }
     118           0 :     }
     119             : 
     120             :     // #112245# helper to evtl. split filled polygons to maximum metafile point count
     121        2614 :     bool fillPolyPolygonNeededToBeSplit(basegfx::B2DPolyPolygon& rPolyPolygon)
     122             :     {
     123        2614 :         bool bRetval(false);
     124        2614 :         const sal_uInt32 nPolyCount(rPolyPolygon.count());
     125             : 
     126        2614 :         if(nPolyCount)
     127             :         {
     128        2614 :             basegfx::B2DPolyPolygon aSplitted;
     129             : 
     130        8244 :             for(sal_uInt32 a(0); a < nPolyCount; a++)
     131             :             {
     132        5630 :                 const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a));
     133        5630 :                 const sal_uInt32 nPointCount(aCandidate.count());
     134        5630 :                 bool bNeedToSplit(false);
     135             : 
     136        5630 :                 if(aCandidate.areControlPointsUsed())
     137             :                 {
     138             :                     // compare with the maximum for bezier curved polygons
     139         368 :                     bNeedToSplit = nPointCount > ((MAX_POLYGON_POINT_COUNT_METAFILE / 3L) - 1L);
     140             :                 }
     141             :                 else
     142             :                 {
     143             :                     // compare with the maximum for simple point polygons
     144        5262 :                     bNeedToSplit = nPointCount > (MAX_POLYGON_POINT_COUNT_METAFILE - 1);
     145             :                 }
     146             : 
     147        5630 :                 if(bNeedToSplit)
     148             :                 {
     149             :                     // need to split the partial polygon
     150           0 :                     const basegfx::B2DRange aRange(aCandidate.getB2DRange());
     151           0 :                     const basegfx::B2DPoint aCenter(aRange.getCenter());
     152             : 
     153           0 :                     if(aRange.getWidth() > aRange.getHeight())
     154             :                     {
     155             :                         // clip in left and right
     156             :                         const basegfx::B2DPolyPolygon aLeft(
     157             :                             basegfx::tools::clipPolygonOnParallelAxis(
     158             :                                 aCandidate,
     159             :                                 false,
     160             :                                 true,
     161             :                                 aCenter.getX(),
     162           0 :                                 false));
     163             :                         const basegfx::B2DPolyPolygon aRight(
     164             :                             basegfx::tools::clipPolygonOnParallelAxis(
     165             :                                 aCandidate,
     166             :                                 false,
     167             :                                 false,
     168             :                                 aCenter.getX(),
     169           0 :                                 false));
     170             : 
     171           0 :                         aSplitted.append(aLeft);
     172           0 :                         aSplitted.append(aRight);
     173             :                     }
     174             :                     else
     175             :                     {
     176             :                         // clip in top and bottom
     177             :                         const basegfx::B2DPolyPolygon aTop(
     178             :                             basegfx::tools::clipPolygonOnParallelAxis(
     179             :                                 aCandidate,
     180             :                                 true,
     181             :                                 true,
     182             :                                 aCenter.getY(),
     183           0 :                                 false));
     184             :                         const basegfx::B2DPolyPolygon aBottom(
     185             :                             basegfx::tools::clipPolygonOnParallelAxis(
     186             :                                 aCandidate,
     187             :                                 true,
     188             :                                 false,
     189             :                                 aCenter.getY(),
     190           0 :                                 false));
     191             : 
     192           0 :                         aSplitted.append(aTop);
     193           0 :                         aSplitted.append(aBottom);
     194           0 :                     }
     195             :                 }
     196             :                 else
     197             :                 {
     198        5630 :                     aSplitted.append(aCandidate);
     199             :                 }
     200        5630 :             }
     201             : 
     202        2614 :             if(aSplitted.count() != nPolyCount)
     203             :             {
     204           0 :                 rPolyPolygon = aSplitted;
     205        2614 :             }
     206             :         }
     207             : 
     208        2614 :         return bRetval;
     209             :     }
     210             : 
     211             :     /** Filter input polypolygon for effectively empty sub-fills
     212             : 
     213             :         Needed to fix fdo#37559
     214             : 
     215             :         @param rPoly
     216             :         tools::PolyPolygon to filter
     217             : 
     218             :         @return converted tools PolyPolygon, w/o one-point fills
     219             :      */
     220          94 :     tools::PolyPolygon getFillPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly )
     221             :     {
     222             :         // filter input rPoly
     223          94 :         basegfx::B2DPolyPolygon aPoly;
     224          94 :         sal_uInt32 nCount(rPoly.count());
     225         676 :         for( sal_uInt32 i=0; i<nCount; ++i )
     226             :         {
     227         582 :             basegfx::B2DPolygon aCandidate(rPoly.getB2DPolygon(i));
     228         582 :             if( !aCandidate.isClosed() || aCandidate.count() > 1 )
     229         410 :                 aPoly.append(aCandidate);
     230         582 :         }
     231          94 :         return tools::PolyPolygon(aPoly);
     232             :     }
     233             : 
     234             : } // end of anonymous namespace
     235             : 
     236             : namespace drawinglayer
     237             : {
     238             :     namespace processor2d
     239             :     {
     240           0 :         Rectangle VclMetafileProcessor2D::impDumpToMetaFile(
     241             :             const primitive2d::Primitive2DSequence& rContent,
     242             :             GDIMetaFile& o_rContentMetafile)
     243             :         {
     244             :             // Prepare VDev, MetaFile and connections
     245           0 :             OutputDevice* pLastOutputDevice = mpOutputDevice;
     246           0 :             GDIMetaFile* pLastMetafile = mpMetaFile;
     247           0 :             basegfx::B2DRange aPrimitiveRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
     248             : 
     249             :             // transform primitive range with current transformation (e.g shadow offset)
     250           0 :             aPrimitiveRange.transform(maCurrentTransformation);
     251             : 
     252             :             const Rectangle aPrimitiveRectangle(
     253           0 :                 basegfx::fround(aPrimitiveRange.getMinX()), basegfx::fround(aPrimitiveRange.getMinY()),
     254           0 :                 basegfx::fround(aPrimitiveRange.getMaxX()), basegfx::fround(aPrimitiveRange.getMaxY()));
     255           0 :             VirtualDevice aContentVDev;
     256           0 :             MapMode aNewMapMode(pLastOutputDevice->GetMapMode());
     257             : 
     258           0 :             mpOutputDevice = &aContentVDev;
     259           0 :             mpMetaFile = &o_rContentMetafile;
     260           0 :             aContentVDev.EnableOutput(false);
     261           0 :             aContentVDev.SetMapMode(pLastOutputDevice->GetMapMode());
     262           0 :             o_rContentMetafile.Record(&aContentVDev);
     263           0 :             aContentVDev.SetLineColor(pLastOutputDevice->GetLineColor());
     264           0 :             aContentVDev.SetFillColor(pLastOutputDevice->GetFillColor());
     265           0 :             aContentVDev.SetFont(pLastOutputDevice->GetFont());
     266           0 :             aContentVDev.SetDrawMode(pLastOutputDevice->GetDrawMode());
     267           0 :             aContentVDev.SetSettings(pLastOutputDevice->GetSettings());
     268           0 :             aContentVDev.SetRefPoint(pLastOutputDevice->GetRefPoint());
     269             : 
     270             :             // dump to MetaFile
     271           0 :             process(rContent);
     272             : 
     273             :             // cleanups
     274           0 :             o_rContentMetafile.Stop();
     275           0 :             o_rContentMetafile.WindStart();
     276           0 :             aNewMapMode.SetOrigin(aPrimitiveRectangle.TopLeft());
     277           0 :             o_rContentMetafile.SetPrefMapMode(aNewMapMode);
     278           0 :             o_rContentMetafile.SetPrefSize(aPrimitiveRectangle.GetSize());
     279           0 :             mpOutputDevice = pLastOutputDevice;
     280           0 :             mpMetaFile = pLastMetafile;
     281             : 
     282           0 :             return aPrimitiveRectangle;
     283             :         }
     284             : 
     285          12 :         void VclMetafileProcessor2D::impConvertFillGradientAttributeToVCLGradient(
     286             :             Gradient& o_rVCLGradient,
     287             :             const attribute::FillGradientAttribute& rFiGrAtt,
     288             :             bool bIsTransparenceGradient)
     289             :         {
     290          12 :             if(bIsTransparenceGradient)
     291             :             {
     292             :                 // it's about transparence channel intensities (black/white), do not use color modifier
     293           0 :                 o_rVCLGradient.SetStartColor(Color(rFiGrAtt.getStartColor()));
     294           0 :                 o_rVCLGradient.SetEndColor(Color(rFiGrAtt.getEndColor()));
     295             :             }
     296             :             else
     297             :             {
     298             :                 // use color modifier to influence start/end color of gradient
     299          12 :                 o_rVCLGradient.SetStartColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getStartColor())));
     300          12 :                 o_rVCLGradient.SetEndColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getEndColor())));
     301             :             }
     302             : 
     303          12 :             o_rVCLGradient.SetAngle(static_cast< sal_uInt16 >(rFiGrAtt.getAngle() * (1.0 / F_PI1800)));
     304          12 :             o_rVCLGradient.SetBorder(static_cast< sal_uInt16 >(rFiGrAtt.getBorder() * 100.0));
     305          12 :             o_rVCLGradient.SetOfsX(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetX() * 100.0));
     306          12 :             o_rVCLGradient.SetOfsY(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetY() * 100.0));
     307          12 :             o_rVCLGradient.SetSteps(rFiGrAtt.getSteps());
     308             : 
     309             :             // defaults for intensity; those were computed into the start/end colors already
     310          12 :             o_rVCLGradient.SetStartIntensity(100);
     311          12 :             o_rVCLGradient.SetEndIntensity(100);
     312             : 
     313          12 :             switch(rFiGrAtt.getStyle())
     314             :             {
     315             :                 default : // attribute::GRADIENTSTYLE_LINEAR :
     316             :                 {
     317           4 :                     o_rVCLGradient.SetStyle(GradientStyle_LINEAR);
     318           4 :                     break;
     319             :                 }
     320             :                 case attribute::GRADIENTSTYLE_AXIAL :
     321             :                 {
     322           8 :                     o_rVCLGradient.SetStyle(GradientStyle_AXIAL);
     323           8 :                     break;
     324             :                 }
     325             :                 case attribute::GRADIENTSTYLE_RADIAL :
     326             :                 {
     327           0 :                     o_rVCLGradient.SetStyle(GradientStyle_RADIAL);
     328           0 :                     break;
     329             :                 }
     330             :                 case attribute::GRADIENTSTYLE_ELLIPTICAL :
     331             :                 {
     332           0 :                     o_rVCLGradient.SetStyle(GradientStyle_ELLIPTICAL);
     333           0 :                     break;
     334             :                 }
     335             :                 case attribute::GRADIENTSTYLE_SQUARE :
     336             :                 {
     337           0 :                     o_rVCLGradient.SetStyle(GradientStyle_SQUARE);
     338           0 :                     break;
     339             :                 }
     340             :                 case attribute::GRADIENTSTYLE_RECT :
     341             :                 {
     342           0 :                     o_rVCLGradient.SetStyle(GradientStyle_RECT);
     343           0 :                     break;
     344             :                 }
     345             :             }
     346          12 :         }
     347             : 
     348          94 :         void VclMetafileProcessor2D::impStartSvtGraphicFill(SvtGraphicFill* pSvtGraphicFill)
     349             :         {
     350          94 :             if(pSvtGraphicFill && !mnSvtGraphicFillCount)
     351             :             {
     352          94 :                 SvMemoryStream aMemStm;
     353             : 
     354          94 :                 WriteSvtGraphicFill( aMemStm, *pSvtGraphicFill );
     355          94 :                 mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_BEGIN", 0, static_cast< const sal_uInt8* >(aMemStm.GetData()), aMemStm.Seek(STREAM_SEEK_TO_END)));
     356          94 :                 mnSvtGraphicFillCount++;
     357             :             }
     358          94 :         }
     359             : 
     360          94 :         void VclMetafileProcessor2D::impEndSvtGraphicFill(SvtGraphicFill* pSvtGraphicFill)
     361             :         {
     362          94 :             if(pSvtGraphicFill && mnSvtGraphicFillCount)
     363             :             {
     364          94 :                 mnSvtGraphicFillCount--;
     365          94 :                 mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_END"));
     366          94 :                 delete pSvtGraphicFill;
     367             :             }
     368          94 :         }
     369             : 
     370        4466 :         double VclMetafileProcessor2D::getTransformedLineWidth( double fWidth ) const
     371             :         {
     372             :             // #i113922# the LineWidth is duplicated in the MetaPolylineAction,
     373             :             // and also inside the SvtGraphicStroke and needs transforming into
     374             :             // the same space as its co-ordinates here cf. fdo#61789
     375             :             // This is a partial fix. When a object transformation is used which
     376             :             // e.g. contains a scaleX != scaleY, an unproportional scaling will happen.
     377        4466 :             const basegfx::B2DVector aDiscreteUnit( maCurrentTransformation * basegfx::B2DVector( fWidth, 0.0 ) );
     378             : 
     379        4466 :             return aDiscreteUnit.getLength();
     380             :         }
     381             : 
     382        3484 :         SvtGraphicStroke* VclMetafileProcessor2D::impTryToCreateSvtGraphicStroke(
     383             :             const basegfx::B2DPolygon& rB2DPolygon,
     384             :             const basegfx::BColor* pColor,
     385             :             const attribute::LineAttribute* pLineAttribute,
     386             :             const attribute::StrokeAttribute* pStrokeAttribute,
     387             :             const attribute::LineStartEndAttribute* pStart,
     388             :             const attribute::LineStartEndAttribute* pEnd)
     389             :         {
     390        3484 :             SvtGraphicStroke* pRetval = 0;
     391             : 
     392        3484 :             if(rB2DPolygon.count() && !mnSvtGraphicStrokeCount)
     393             :             {
     394        3386 :                 basegfx::B2DPolygon aLocalPolygon(rB2DPolygon);
     395        6772 :                 basegfx::BColor aStrokeColor;
     396        6772 :                 basegfx::B2DPolyPolygon aStartArrow;
     397        6772 :                 basegfx::B2DPolyPolygon aEndArrow;
     398             : 
     399        3386 :                 if(pColor)
     400             :                 {
     401           0 :                     aStrokeColor = *pColor;
     402             :                 }
     403        3386 :                 else if(pLineAttribute)
     404             :                 {
     405        3386 :                     aStrokeColor = maBColorModifierStack.getModifiedColor(pLineAttribute->getColor());
     406             :                 }
     407             : 
     408             :                 // It IS needed to record the stroke color at all in the metafile,
     409             :                 // SvtGraphicStroke has NO entry for stroke color(!)
     410        3386 :                 mpOutputDevice->SetLineColor(Color(aStrokeColor));
     411             : 
     412        3386 :                 if(!aLocalPolygon.isClosed())
     413             :                 {
     414         498 :                     double fPolyLength(0.0);
     415         498 :                     double fStart(0.0);
     416         498 :                     double fEnd(0.0);
     417             : 
     418         498 :                     if(pStart && pStart->isActive())
     419             :                     {
     420          78 :                         fPolyLength = basegfx::tools::getLength(aLocalPolygon);
     421             : 
     422         234 :                         aStartArrow = basegfx::tools::createAreaGeometryForLineStartEnd(
     423          78 :                             aLocalPolygon, pStart->getB2DPolyPolygon(), true, pStart->getWidth(),
     424         156 :                             fPolyLength, pStart->isCentered() ? 0.5 : 0.0, &fStart);
     425             :                     }
     426             : 
     427         498 :                     if(pEnd && pEnd->isActive())
     428             :                     {
     429          98 :                         if(basegfx::fTools::equalZero(fPolyLength))
     430             :                         {
     431          72 :                             fPolyLength = basegfx::tools::getLength(aLocalPolygon);
     432             :                         }
     433             : 
     434         294 :                         aEndArrow = basegfx::tools::createAreaGeometryForLineStartEnd(
     435          98 :                             aLocalPolygon, pEnd->getB2DPolyPolygon(), false, pEnd->getWidth(),
     436         196 :                             fPolyLength, pEnd->isCentered() ? 0.5 : 0.0, &fEnd);
     437             :                     }
     438             : 
     439         498 :                     if(0.0 != fStart || 0.0 != fEnd)
     440             :                     {
     441             :                         // build new poly, consume something from old poly
     442          98 :                         aLocalPolygon = basegfx::tools::getSnippetAbsolute(aLocalPolygon, fStart, fPolyLength - fEnd, fPolyLength);
     443             :                     }
     444             :                 }
     445             : 
     446        3386 :                 SvtGraphicStroke::JoinType eJoin(SvtGraphicStroke::joinNone);
     447        3386 :                 SvtGraphicStroke::CapType eCap(SvtGraphicStroke::capButt);
     448        3386 :                 double fLineWidth(0.0);
     449        3386 :                 double fMiterLength(0.0);
     450        6772 :                 SvtGraphicStroke::DashArray aDashArray;
     451             : 
     452        3386 :                 if(pLineAttribute)
     453             :                 {
     454        3386 :                     fLineWidth = fMiterLength = getTransformedLineWidth( pLineAttribute->getWidth() );
     455             : 
     456             :                     // get Join
     457        3386 :                     switch(pLineAttribute->getLineJoin())
     458             :                     {
     459             :                         default : // basegfx::B2DLINEJOIN_NONE :
     460             :                         {
     461           6 :                             eJoin = SvtGraphicStroke::joinNone;
     462           6 :                             break;
     463             :                         }
     464             :                         case basegfx::B2DLINEJOIN_BEVEL :
     465             :                         {
     466         312 :                             eJoin = SvtGraphicStroke::joinBevel;
     467         312 :                             break;
     468             :                         }
     469             :                         case basegfx::B2DLINEJOIN_MIDDLE :
     470             :                         case basegfx::B2DLINEJOIN_MITER :
     471             :                         {
     472         404 :                             eJoin = SvtGraphicStroke::joinMiter;
     473             :                             // ATM 15 degrees is assumed
     474         404 :                             fMiterLength /= rtl::math::sin(M_PI * (15.0 / 360.0));
     475         404 :                             break;
     476             :                         }
     477             :                         case basegfx::B2DLINEJOIN_ROUND :
     478             :                         {
     479        2664 :                             eJoin = SvtGraphicStroke::joinRound;
     480        2664 :                             break;
     481             :                         }
     482             :                     }
     483             : 
     484             :                     // get stroke
     485        3386 :                     switch(pLineAttribute->getLineCap())
     486             :                     {
     487             :                         default: /* com::sun::star::drawing::LineCap_BUTT */
     488             :                         {
     489        3380 :                             eCap = SvtGraphicStroke::capButt;
     490        3380 :                             break;
     491             :                         }
     492             :                         case com::sun::star::drawing::LineCap_ROUND:
     493             :                         {
     494           6 :                             eCap = SvtGraphicStroke::capRound;
     495           6 :                             break;
     496             :                         }
     497             :                         case com::sun::star::drawing::LineCap_SQUARE:
     498             :                         {
     499           0 :                             eCap = SvtGraphicStroke::capSquare;
     500           0 :                             break;
     501             :                         }
     502             :                     }
     503             :                 }
     504             : 
     505        3386 :                 if(pStrokeAttribute)
     506             :                 {
     507             :                     // copy dash array
     508        3386 :                     aDashArray = pStrokeAttribute->getDotDashArray();
     509             :                 }
     510             : 
     511             :                 // #i101734# apply current object transformation to created geometry.
     512             :                 // This is a partial fix. When a object transformation is used which
     513             :                 // e.g. contains a scaleX != scaleY, an unproportional scaling would
     514             :                 // have to be applied to the evtl. existing fat line. The current
     515             :                 // concept of PDF export and SvtGraphicStroke usage does simply not
     516             :                 // allow handling such definitions. The only clean way would be to
     517             :                 // add the transformation to SvtGraphicStroke and to handle it there
     518        3386 :                 aLocalPolygon.transform(maCurrentTransformation);
     519        3386 :                 aStartArrow.transform(maCurrentTransformation);
     520        3386 :                 aEndArrow.transform(maCurrentTransformation);
     521             : 
     522             :                 pRetval = new SvtGraphicStroke(
     523             :                     Polygon(aLocalPolygon),
     524             :                     tools::PolyPolygon(aStartArrow),
     525             :                     tools::PolyPolygon(aEndArrow),
     526             :                     mfCurrentUnifiedTransparence,
     527             :                     fLineWidth,
     528             :                     eCap,
     529             :                     eJoin,
     530             :                     fMiterLength,
     531        6772 :                     aDashArray);
     532             :             }
     533             : 
     534        3484 :             return pRetval;
     535             :         }
     536             : 
     537        3484 :         void VclMetafileProcessor2D::impStartSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke)
     538             :         {
     539        3484 :             if(pSvtGraphicStroke && !mnSvtGraphicStrokeCount)
     540             :             {
     541        3386 :                 SvMemoryStream aMemStm;
     542             : 
     543        3386 :                 WriteSvtGraphicStroke( aMemStm, *pSvtGraphicStroke );
     544        3386 :                 mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_BEGIN", 0, static_cast< const sal_uInt8* >(aMemStm.GetData()), aMemStm.Seek(STREAM_SEEK_TO_END)));
     545        3386 :                 mnSvtGraphicStrokeCount++;
     546             :             }
     547        3484 :         }
     548             : 
     549        3484 :         void VclMetafileProcessor2D::impEndSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke)
     550             :         {
     551        3484 :             if(pSvtGraphicStroke && mnSvtGraphicStrokeCount)
     552             :             {
     553        3386 :                 mnSvtGraphicStrokeCount--;
     554        3386 :                 mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_END"));
     555        3386 :                 delete pSvtGraphicStroke;
     556             :             }
     557        3484 :         }
     558             : 
     559             :         // init static break iterator
     560         381 :         uno::Reference< ::com::sun::star::i18n::XBreakIterator > VclMetafileProcessor2D::mxBreakIterator;
     561             : 
     562        1410 :         VclMetafileProcessor2D::VclMetafileProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev)
     563             :         :   VclProcessor2D(rViewInformation, rOutDev),
     564        1410 :             mpMetaFile(rOutDev.GetConnectMetaFile()),
     565             :             mnSvtGraphicFillCount(0),
     566             :             mnSvtGraphicStrokeCount(0),
     567             :             mfCurrentUnifiedTransparence(0.0),
     568        2820 :             mpPDFExtOutDevData(dynamic_cast< vcl::PDFExtOutDevData* >(rOutDev.GetExtOutDevData()))
     569             :         {
     570             :             OSL_ENSURE(rOutDev.GetConnectMetaFile(), "VclMetafileProcessor2D: Used on OutDev which has no MetaFile Target (!)");
     571             :             // draw to logic coordinates, do not initialize maCurrentTransformation to viewTransformation
     572             :             // but only to ObjectTransformation. Do not change MapMode of destination.
     573        1410 :             maCurrentTransformation = rViewInformation.getObjectTransformation();
     574        1410 :         }
     575             : 
     576        2820 :         VclMetafileProcessor2D::~VclMetafileProcessor2D()
     577             :         {
     578             :             // MapMode was not changed, no restore necessary
     579        2820 :         }
     580             : 
     581             :         /***********************************************************************************************
     582             : 
     583             :             Support of MetaCommentActions in the VclMetafileProcessor2D
     584             :             Found MetaCommentActions and how they are supported:
     585             : 
     586             :             XGRAD_SEQ_BEGIN, XGRAD_SEQ_END:
     587             : 
     588             :             Used inside OutputDevice::DrawGradient to mark the start and end of a MetaGradientEx action.
     589             :             It is used in various exporters/importers to have direct access to the gradient before it
     590             :             is rendered by VCL (and thus fragmented to polygon color actions and others). On that base, e.g.
     591             :             the Metafile to SdrObject import creates it's gradient objects.
     592             :             Best (and safest) way to support it here is to use PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
     593             :             map it back to the corresponding tools tools::PolyPolygon and the Gradient and just call
     594             :             OutputDevice::DrawGradient which creates the necessary compatible actions.
     595             : 
     596             :             XPATHFILL_SEQ_BEGIN, XPATHFILL_SEQ_END:
     597             : 
     598             :             Two producers, one is vcl/source/gdi/gdimtf.cxx, line 1273. There, it is transformed
     599             :             inside GDIMetaFile::Rotate, nothing to take care of here.
     600             :             The second producer is in graphics/svx/source/svdraw/impgrfll.cxx, line 374. This is used
     601             :             with each incarnation of Imp_GraphicFill when a metafile is recorded, fillstyle is not
     602             :             XFILL_NONE and not completely transparent. It creates a SvtGraphicFill and streams it
     603             :             to the comment action. A closing end token is created in the destructor.
     604             :             Usages of Imp_GraphicFill are in Do_Paint_Object-methods of SdrCircObj, SdrPathObj and
     605             :             SdrRectObj.
     606             :             The token users pick various actions from SvtGraphicFill, so it may need to be added for all kind
     607             :             of filled objects, even simple colored polygons. It is added as extra information; the
     608             :             Metafile actions between the two tokens are interpreted as output generated from those
     609             :             fills. Thus, users have the choice to use the SvtGraphicFill info or the created output
     610             :             actions.
     611             :             Even for XFillTransparenceItem it is used, thus it may need to be supported in
     612             :             UnifiedTransparencePrimitive2D, too, when interpreted as normally filled PolyPolygon.
     613             :             Implemented for:
     614             :                 PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D,
     615             :                 PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D,
     616             :                 PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
     617             :                 PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D,
     618             :                 and for PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D when detected unified transparence
     619             : 
     620             :             XPATHSTROKE_SEQ_BEGIN, XPATHSTROKE_SEQ_END:
     621             : 
     622             :             Similar to pathfill, but using SvtGraphicStroke instead. It also has two producers where one
     623             :             is also the GDIMetaFile::Rotate. Another user is MetaCommentAction::Move which modifies the
     624             :             contained path accordingly.
     625             :             The other one is SdrObject::Imp_DrawLineGeometry. It's done when MetaFile is set at OutDev and
     626             :             only when geometry is a single polygon (!). I see no reason for that; in the PS exporter this
     627             :             would hinder to make use of tools::PolyPolygon strokes. I will need to add support at:
     628             :                 PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D
     629             :                 PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D
     630             :                 PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D
     631             :             This can be done hierarchical, too.
     632             :             Okay, base implementation done based on those three primitives.
     633             : 
     634             :             FIELD_SEQ_BEGIN, FIELD_SEQ_END
     635             : 
     636             :             Used from slideshow for URLs, created from diverse SvxField implementations inside
     637             :             createBeginComment()/createEndComment(). createBeginComment() is used from editeng\impedit3.cxx
     638             :             inside ImpEditEngine::Paint.
     639             :             Created TextHierarchyFieldPrimitive2D and added needed infos there; it is an group primitive and wraps
     640             :             text primitives (but is not limited to that). It contains the field type if special actions for the
     641             :             support of FIELD_SEQ_BEGIN/END are needed; this is the case for Page and URL fields. If more is
     642             :             needed, it may be supported there.
     643             :             FIELD_SEQ_BEGIN;PageField
     644             :             FIELD_SEQ_END
     645             :             Okay, these are now completely supported by TextHierarchyFieldPrimitive2D. URL works, too.
     646             : 
     647             :             XTEXT
     648             : 
     649             :             XTEXT_EOC(i) end of character
     650             :             XTEXT_EOW(i) end of word
     651             :             XTEXT_EOS(i) end of sentence
     652             : 
     653             :             this three are with index and are created with the help of a i18n::XBreakIterator in
     654             :             ImplDrawWithComments. Simplifying, moving out text painting, reworking to create some
     655             :             data structure for holding those TEXT infos.
     656             :             Supported directly by TextSimplePortionPrimitive2D with adding a Locale to the basic text
     657             :             primitive. In the MetaFileRenderer, the creation is now done (see below). This has the advantage
     658             :             that this creations do not need to be done for all paints all the time. This would be
     659             :             expensive since the BreakIterator and it's usage is expensive and for each paint also the
     660             :             whole character stops would need to be created.
     661             :             Created only for TextDecoratedPortionPrimitive2D due to XTEXT_EOL and XTEXT_EOP (see below)
     662             : 
     663             :             XTEXT_EOL() end of line
     664             :             XTEXT_EOP() end of paragraph
     665             : 
     666             :             First try with boolean marks at TextDecoratedPortionPrimitive2D did not work too well,
     667             :             i decided to solve it with structure. I added the TextHierarchyPrimitives for this,
     668             :             namely:
     669             :             - TextHierarchyLinePrimitive2D: Encapsulates single line
     670             :             - TextHierarchyParagraphPrimitive2D: Encapsulates single paragraph
     671             :             - TextHierarchyBlockPrimitive2D: encapsulates object texts (only one ATM)
     672             :             Those are now supported in hierarchy. This means the MetaFile renderer will support them
     673             :             by using them, reculrively using their content and adding MetaFile comments as needed.
     674             :             This also means that when another text layouter will be used it will be necessary to
     675             :             create/support the same HierarchyPrimitives to support users.
     676             :             To transport the information using this hierarchy is best suited to all future needs;
     677             :             the slideshow will be able to profit from it directly when using primitives; all other
     678             :             renderers not interested in the text structure will just ignore the encapsulations.
     679             : 
     680             :             XTEXT_PAINTSHAPE_BEGIN, XTEXT_PAINTSHAPE_END
     681             :             Supported now by the TextHierarchyBlockPrimitive2D.
     682             : 
     683             :             EPSReplacementGraphic:
     684             :             Only used in goodies\source\filter.vcl\ieps\ieps.cxx and svx\source\xml\xmlgrhlp.cxx to
     685             :             hold the original EPS which was imported in the same MetaFile as first 2 entries. Only
     686             :             used to export the original again (if exists).
     687             :             Not necessary to support with MetaFuleRenderer.
     688             : 
     689             :             XTEXT_SCROLLRECT, XTEXT_PAINTRECT
     690             :             Currently used to get extra MetaFile infos using GraphicExporter which again uses
     691             :             SdrTextObj::GetTextScrollMetaFileAndRectangle(). ATM works with primitives since
     692             :             the rectangle data is added directly by the GraphicsExporter as comment. Does not need
     693             :             to be adapted at once.
     694             :             When adapting later, the only user - the diashow - should directly use the provided
     695             :             Anination infos in the appropriate primitives (e.g. AnimatedSwitchPrimitive2D)
     696             : 
     697             :             PRNSPOOL_TRANSPARENTBITMAP_BEGIN, PRNSPOOL_TRANSPARENTBITMAP_END
     698             :             VCL usage when printing PL -> THB. Okay, THB confirms that it is only used as
     699             :             a fix (hack) while VCL printing. It is needed to not downscale a bitmap which
     700             :             was explicitly created for the printer already again to some default maximum
     701             :             bitmap sizes.
     702             :             Nothing to do here for the primitive renderer.
     703             : 
     704             :             Support for vcl::PDFExtOutDevData:
     705             :             PL knows that SJ did that stuff, it's used to hold a pointer to PDFExtOutDevData at
     706             :             the OutDev. When set, some extra data is written there. Trying simple PDF export and
     707             :             watching if i get those infos.
     708             :             Well, a PDF export does not use e.g. ImpEditEngine::Paint since the PdfFilter uses
     709             :             the SdXImpressDocument::render and thus uses the VclMetafileProcessor2D. I will check
     710             :             if i get a PDFExtOutDevData at the target output device.
     711             :             Indeed, i get one. Checking what all may be done when that extra-device-info is there.
     712             : 
     713             :             All in all i have to talk to SJ. I will need to emulate some of those actions, but
     714             :             i need to discuss which ones.
     715             :             In the future, all those infos would be taken from the primitive sequence anyways,
     716             :             thus these extensions would potentially be temporary, too.
     717             :             Discussed with SJ, added the necessary support and tested it. Details follow.
     718             : 
     719             :             - In ImpEditEngine::Paint, paragraph infos and URL stuff is added.
     720             :               Added in primitive MetaFile renderer.
     721             :               Checking URL: Indeed, current version exports it, but it is missing in primitive
     722             :               CWS version. Adding support.
     723             :               Okay, URLs work. Checked, Done.
     724             : 
     725             :             - UnoControlPDFExportContact is only created when PDFExtOutDevData is used at the
     726             :               target and uno control data is created in UnoControlPDFExportContact::do_PaintObject.
     727             :               This may be added in primitive MetaFile renderer.
     728             :               Adding support...
     729             :               OOps, the necessary helper stuff is in svx/source/form/formpdxexport.cxx in namespace
     730             :               svxform. Have to talk to FS if this has to be like that. Especially since
     731             :               ::vcl::PDFWriter::AnyWidget is filled out, which is already part of vcl.
     732             :               Wrote an eMail to FS, he is on vacation currently. I see no reason why not to move
     733             :               that stuff to somewhere else, maybe tools or svtools ?!? We will see...
     734             :               Moved to toolkit, so i have to link against it. I tried VCL first, but it did
     735             :               not work since VCLUnoHelper::CreateFont is unresolved in VCL (!). Other then the name
     736             :               may imply, it is defined in toolkit (!). Since toolkit is linked against VCL itself,
     737             :               the lowest move,ment plave is toolkit.
     738             :               Checked form control export, it works well. Done.
     739             : 
     740             :             - In goodies, in GraphicObject::Draw, when the used Graphic is linked, infos are
     741             :               generated. I will need to check what happens here with primitives.
     742             :               To support, use of GraphicPrimitive2D (PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D) may be needed.
     743             :               Added support, but feature is broken in main version, so i cannot test at all.
     744             :               Writing a bug to CL (or SJ) and seeing what happens (#i80380#).
     745             :               SJ took a look and we got it working. Tested VCL MetaFile Renderer based export,
     746             :               as intended, the original file is exported. Works, Done.
     747             : 
     748             : 
     749             : 
     750             : 
     751             :             To be done:
     752             : 
     753             :             - Maybe there are more places to take care of for vcl::PDFExtOutDevData!
     754             : 
     755             : 
     756             : 
     757             :         ****************************************************************************************************/
     758             : 
     759       24084 :         void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
     760             :         {
     761       24084 :             switch(rCandidate.getPrimitive2DID())
     762             :             {
     763             :                 case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
     764             :                 {
     765             :                     // directdraw of wrong spell primitive
     766             :                     // Ignore for VclMetafileProcessor2D, this is for printing and MetaFile recording only
     767           0 :                     break;
     768             :                 }
     769             :                 case PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D :
     770             :                 {
     771         268 :                     const primitive2d::GraphicPrimitive2D& rGraphicPrimitive = static_cast< const primitive2d::GraphicPrimitive2D& >(rCandidate);
     772         268 :                     bool bUsingPDFExtOutDevData(false);
     773         536 :                     basegfx::B2DVector aTranslate, aScale;
     774             :                     static bool bSuppressPDFExtOutDevDataSupport(false);
     775             : 
     776         268 :                     if(mpPDFExtOutDevData && !bSuppressPDFExtOutDevDataSupport)
     777             :                     {
     778             :                         // emulate data handling from UnoControlPDFExportContact, original see
     779             :                         // svtools/source/graphic/grfmgr.cxx
     780           0 :                         const Graphic& rGraphic = rGraphicPrimitive.getGraphicObject().GetGraphic();
     781             : 
     782           0 :                         if(rGraphic.IsLink())
     783             :                         {
     784           0 :                             const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
     785             : 
     786           0 :                             if(!rAttr.IsSpecialDrawMode() && !rAttr.IsAdjusted())
     787             :                             {
     788           0 :                                 const basegfx::B2DHomMatrix& rTransform = rGraphicPrimitive.getTransform();
     789             :                                 double fRotate, fShearX;
     790           0 :                                 rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
     791             : 
     792           0 :                                 if( basegfx::fTools::equalZero( fRotate ) && ( aScale.getX() > 0.0 ) && ( aScale.getY() > 0.0 ) )
     793             :                                 {
     794           0 :                                     bUsingPDFExtOutDevData = true;
     795           0 :                                     mpPDFExtOutDevData->BeginGroup();
     796             :                                 }
     797             :                             }
     798             :                         }
     799             :                     }
     800             : 
     801             :                     // process recursively and add MetaFile comment
     802         268 :                     process(rGraphicPrimitive.get2DDecomposition(getViewInformation2D()));
     803             : 
     804         268 :                     if(bUsingPDFExtOutDevData)
     805             :                     {
     806             :                         // emulate data handling from UnoControlPDFExportContact, original see
     807             :                         // svtools/source/graphic/grfmgr.cxx
     808             :                         const basegfx::B2DRange aCurrentRange(
     809             :                             aTranslate.getX(), aTranslate.getY(),
     810           0 :                             aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
     811             :                         const Rectangle aCurrentRect(
     812           0 :                             sal_Int32(floor(aCurrentRange.getMinX())), sal_Int32(floor(aCurrentRange.getMinY())),
     813           0 :                             sal_Int32(ceil(aCurrentRange.getMaxX())), sal_Int32(ceil(aCurrentRange.getMaxY())));
     814           0 :                         const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
     815             :                         // fdo#72530 don't pass empty Rectangle to EndGroup
     816           0 :                         Rectangle aCropRect(aCurrentRect);
     817             : 
     818           0 :                         if(rAttr.IsCropped())
     819             :                         {
     820             :                             // calculate scalings between real image size and logic object size. This
     821             :                             // is necessary since the crop values are relative to original bitmap size
     822           0 :                             double fFactorX(1.0);
     823           0 :                             double fFactorY(1.0);
     824             : 
     825             :                             {
     826           0 :                                 const MapMode aMapMode100thmm(MAP_100TH_MM);
     827             :                                 const Size aBitmapSize(OutputDevice::LogicToLogic(
     828           0 :                                     rGraphicPrimitive.getGraphicObject().GetPrefSize(),
     829           0 :                                     rGraphicPrimitive.getGraphicObject().GetPrefMapMode(), aMapMode100thmm));
     830           0 :                                 const double fDivX(aBitmapSize.Width() - rAttr.GetLeftCrop() - rAttr.GetRightCrop());
     831           0 :                                 const double fDivY(aBitmapSize.Height() - rAttr.GetTopCrop() - rAttr.GetBottomCrop());
     832             : 
     833           0 :                                 if(!basegfx::fTools::equalZero(fDivX))
     834             :                                 {
     835           0 :                                     fFactorX = aScale.getX() / fDivX;
     836             :                                 }
     837             : 
     838           0 :                                 if(!basegfx::fTools::equalZero(fDivY))
     839             :                                 {
     840           0 :                                     fFactorY = aScale.getY() / fDivY;
     841           0 :                                 }
     842             :                             }
     843             : 
     844             :                             // calculate crop range and rect
     845           0 :                             basegfx::B2DRange aCropRange;
     846           0 :                             aCropRange.expand(aCurrentRange.getMinimum() - basegfx::B2DPoint(rAttr.GetLeftCrop() * fFactorX, rAttr.GetTopCrop() * fFactorY));
     847           0 :                             aCropRange.expand(aCurrentRange.getMaximum() + basegfx::B2DPoint(rAttr.GetRightCrop() * fFactorX, rAttr.GetBottomCrop() * fFactorY));
     848             : 
     849             :                             aCropRect = Rectangle(
     850           0 :                                 sal_Int32(floor(aCropRange.getMinX())), sal_Int32(floor(aCropRange.getMinY())),
     851           0 :                                 sal_Int32(ceil(aCropRange.getMaxX())), sal_Int32(ceil(aCropRange.getMaxY())));
     852             :                         }
     853             : 
     854             :                         // #i123295# 3rd param is uncropped rect, 4th is cropped. The primitive has the cropped
     855             :                         // object transformation, thus aCurrentRect *is* the clip region while aCropRect is the expanded,
     856             :                         // uncropped region. Thus, correct order is aCropRect, aCurrentRect
     857           0 :                         mpPDFExtOutDevData->EndGroup(rGraphicPrimitive.getGraphicObject().GetGraphic(),
     858           0 :                             rAttr.GetTransparency(),
     859             :                             aCropRect,
     860           0 :                             aCurrentRect);
     861             :                     }
     862             : 
     863         536 :                     break;
     864             :                 }
     865             :                 case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
     866             :                 {
     867           2 :                     const primitive2d::ControlPrimitive2D& rControlPrimitive = static_cast< const primitive2d::ControlPrimitive2D& >(rCandidate);
     868           2 :                     const uno::Reference< awt::XControl >& rXControl(rControlPrimitive.getXControl());
     869           2 :                     bool bIsPrintableControl(false);
     870             : 
     871             :                     // find out if control is printable
     872           2 :                     if(rXControl.is())
     873             :                     {
     874             :                         try
     875             :                         {
     876           2 :                             uno::Reference< beans::XPropertySet > xModelProperties(rXControl->getModel(), uno::UNO_QUERY);
     877           2 :                             uno::Reference< beans::XPropertySetInfo > xPropertyInfo(xModelProperties.is()
     878           2 :                                 ? xModelProperties->getPropertySetInfo()
     879           6 :                                 : uno::Reference< beans::XPropertySetInfo >());
     880           4 :                             const OUString sPrintablePropertyName("Printable");
     881             : 
     882           2 :                             if(xPropertyInfo.is() && xPropertyInfo->hasPropertyByName(sPrintablePropertyName))
     883             :                             {
     884           2 :                                 OSL_VERIFY(xModelProperties->getPropertyValue(sPrintablePropertyName) >>= bIsPrintableControl);
     885           2 :                             }
     886             :                         }
     887           0 :                         catch(const uno::Exception&)
     888             :                         {
     889             :                             OSL_FAIL("VclMetafileProcessor2D: No access to printable flag of Control, caught an exception!");
     890             :                         }
     891             :                     }
     892             : 
     893             :                     // PDF export and printing only for printable controls
     894           2 :                     if(bIsPrintableControl)
     895             :                     {
     896           2 :                         const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields());
     897           2 :                         bool bDoProcessRecursively(true);
     898             : 
     899           2 :                         if(bPDFExport)
     900             :                         {
     901             :                             // PDF export. Emulate data handling from UnoControlPDFExportContact
     902             :                             // I have now moved describePDFControl to toolkit, thus i can implement the PDF
     903             :                             // form control support now as follows
     904             :                             ::std::unique_ptr< ::vcl::PDFWriter::AnyWidget > pPDFControl(
     905           0 :                                 ::toolkitform::describePDFControl( rXControl, *mpPDFExtOutDevData ) );
     906             : 
     907           0 :                             if(pPDFControl.get())
     908             :                             {
     909             :                                 // still need to fill in the location (is a class Rectangle)
     910           0 :                                 const basegfx::B2DRange aRangeLogic(rControlPrimitive.getB2DRange(getViewInformation2D()));
     911             :                                 const Rectangle aRectLogic(
     912           0 :                                     (sal_Int32)floor(aRangeLogic.getMinX()), (sal_Int32)floor(aRangeLogic.getMinY()),
     913           0 :                                     (sal_Int32)ceil(aRangeLogic.getMaxX()), (sal_Int32)ceil(aRangeLogic.getMaxY()));
     914           0 :                                 pPDFControl->Location = aRectLogic;
     915             : 
     916           0 :                                 Size aFontSize(pPDFControl->TextFont.GetSize());
     917           0 :                                 aFontSize = OutputDevice::LogicToLogic(aFontSize, MapMode(MAP_POINT), mpOutputDevice->GetMapMode());
     918           0 :                                 pPDFControl->TextFont.SetSize(aFontSize);
     919             : 
     920           0 :                                 mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Form);
     921           0 :                                 mpPDFExtOutDevData->CreateControl(*pPDFControl.get());
     922           0 :                                 mpPDFExtOutDevData->EndStructureElement();
     923             : 
     924             :                                 // no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject);
     925             :                                 // do not process recursively
     926           0 :                                 bDoProcessRecursively = false;
     927             :                             }
     928             :                             else
     929             :                             {
     930             :                                 // PDF export did not work, try simple output.
     931             :                                 // Fallback to printer output by not setting bDoProcessRecursively
     932             :                                 // to false.
     933           0 :                             }
     934             :                         }
     935             : 
     936             :                         // #i93169# used flag the wrong way; true means that nothing was done yet
     937           2 :                         if(bDoProcessRecursively)
     938             :                         {
     939             :                             // printer output
     940             :                             try
     941             :                             {
     942             :                                 // remember old graphics and create new
     943           2 :                                 uno::Reference< awt::XView > xControlView(rXControl, uno::UNO_QUERY_THROW);
     944           4 :                                 const uno::Reference< awt::XGraphics > xOriginalGraphics(xControlView->getGraphics());
     945           4 :                                 const uno::Reference< awt::XGraphics > xNewGraphics(mpOutputDevice->CreateUnoGraphics());
     946             : 
     947           2 :                                 if(xNewGraphics.is())
     948             :                                 {
     949             :                                     // link graphics and view
     950           2 :                                     xControlView->setGraphics(xNewGraphics);
     951             : 
     952             :                                     // get position
     953           2 :                                     const basegfx::B2DHomMatrix aObjectToDiscrete(getViewInformation2D().getObjectToViewTransformation() * rControlPrimitive.getTransform());
     954           4 :                                     const basegfx::B2DPoint aTopLeftDiscrete(aObjectToDiscrete * basegfx::B2DPoint(0.0, 0.0));
     955             : 
     956             :                                     // draw it
     957           2 :                                     xControlView->draw(basegfx::fround(aTopLeftDiscrete.getX()), basegfx::fround(aTopLeftDiscrete.getY()));
     958           2 :                                     bDoProcessRecursively = false;
     959             : 
     960             :                                     // restore original graphics
     961           4 :                                     xControlView->setGraphics(xOriginalGraphics);
     962           2 :                                 }
     963             :                             }
     964           0 :                             catch( const uno::Exception& )
     965             :                             {
     966             :                                 OSL_FAIL("VclMetafileProcessor2D: Printing of Control failed, caught an exception!");
     967             :                             }
     968             :                         }
     969             : 
     970             :                         // process recursively if not done yet to export as decomposition (bitmap)
     971           2 :                         if(bDoProcessRecursively)
     972             :                         {
     973           0 :                             process(rControlPrimitive.get2DDecomposition(getViewInformation2D()));
     974             :                         }
     975             :                     }
     976             : 
     977           2 :                     break;
     978             :                 }
     979             :                 case PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D :
     980             :                 {
     981             :                     // support for FIELD_SEQ_BEGIN, FIELD_SEQ_END and URL. It wraps text primitives (but is not limited to)
     982             :                     // thus do the MetafileAction embedding stuff but just handle recursively.
     983           4 :                     const primitive2d::TextHierarchyFieldPrimitive2D& rFieldPrimitive = static_cast< const primitive2d::TextHierarchyFieldPrimitive2D& >(rCandidate);
     984           4 :                     const OString aCommentStringCommon("FIELD_SEQ_BEGIN");
     985           8 :                     const OString aCommentStringPage("FIELD_SEQ_BEGIN;PageField");
     986           8 :                     const OString aCommentStringEnd("FIELD_SEQ_END");
     987             : 
     988           4 :                     switch(rFieldPrimitive.getType())
     989             :                     {
     990             :                         default : // case drawinglayer::primitive2d::FIELD_TYPE_COMMON :
     991             :                         {
     992           4 :                             mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon));
     993           4 :                             break;
     994             :                         }
     995             :                         case drawinglayer::primitive2d::FIELD_TYPE_PAGE :
     996             :                         {
     997           0 :                             mpMetaFile->AddAction(new MetaCommentAction(aCommentStringPage));
     998           0 :                             break;
     999             :                         }
    1000             :                         case drawinglayer::primitive2d::FIELD_TYPE_URL :
    1001             :                         {
    1002           0 :                             const OUString& rURL = rFieldPrimitive.getString();
    1003           0 :                             const OUString aOldString(rURL);
    1004           0 :                             mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast< const sal_uInt8* >(aOldString.getStr()), 2 * aOldString.getLength()));
    1005           0 :                             break;
    1006             :                         }
    1007             :                     }
    1008             : 
    1009             :                     // process recursively
    1010           4 :                     const primitive2d::Primitive2DSequence rContent = rFieldPrimitive.get2DDecomposition(getViewInformation2D());
    1011           4 :                     process(rContent);
    1012             : 
    1013             :                     // for the end comment the type is not relevant yet, they are all the same. Just add.
    1014           4 :                     mpMetaFile->AddAction(new MetaCommentAction(aCommentStringEnd));
    1015             : 
    1016           4 :                     if(mpPDFExtOutDevData && drawinglayer::primitive2d::FIELD_TYPE_URL == rFieldPrimitive.getType())
    1017             :                     {
    1018             :                         // emulate data handling from ImpEditEngine::Paint
    1019           0 :                         const basegfx::B2DRange aViewRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
    1020             :                         const Rectangle aRectLogic(
    1021           0 :                             (sal_Int32)floor(aViewRange.getMinX()), (sal_Int32)floor(aViewRange.getMinY()),
    1022           0 :                             (sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY()));
    1023           0 :                         vcl::PDFExtOutDevBookmarkEntry aBookmark;
    1024           0 :                         aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic);
    1025           0 :                         aBookmark.aBookmark = rFieldPrimitive.getString();
    1026           0 :                         std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = mpPDFExtOutDevData->GetBookmarks();
    1027           0 :                         rBookmarks.push_back( aBookmark );
    1028             :                     }
    1029             : 
    1030           8 :                     break;
    1031             :                 }
    1032             :                 case PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D :
    1033             :                 {
    1034         774 :                     const primitive2d::TextHierarchyLinePrimitive2D& rLinePrimitive = static_cast< const primitive2d::TextHierarchyLinePrimitive2D& >(rCandidate);
    1035         774 :                     const OString aCommentString("XTEXT_EOL");
    1036             : 
    1037             :                     // process recursively and add MetaFile comment
    1038         774 :                     process(rLinePrimitive.get2DDecomposition(getViewInformation2D()));
    1039         774 :                     mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
    1040             : 
    1041         774 :                     break;
    1042             :                 }
    1043             :                 case PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D :
    1044             :                 {
    1045             :                     // in Outliner::PaintBullet(), a MetafileComment for bullets is added, too. The
    1046             :                     // "XTEXT_EOC" is used, use here, too.
    1047          36 :                     const primitive2d::TextHierarchyBulletPrimitive2D& rBulletPrimitive = static_cast< const primitive2d::TextHierarchyBulletPrimitive2D& >(rCandidate);
    1048          36 :                     const OString aCommentString("XTEXT_EOC");
    1049             : 
    1050             :                     // process recursively and add MetaFile comment
    1051          36 :                     process(rBulletPrimitive.get2DDecomposition(getViewInformation2D()));
    1052          36 :                     mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
    1053             : 
    1054          36 :                     break;
    1055             :                 }
    1056             :                 case PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D :
    1057             :                 {
    1058         714 :                     const primitive2d::TextHierarchyParagraphPrimitive2D& rParagraphPrimitive = static_cast< const primitive2d::TextHierarchyParagraphPrimitive2D& >(rCandidate);
    1059         714 :                     const OString aCommentString("XTEXT_EOP");
    1060             : 
    1061         714 :                     if(mpPDFExtOutDevData)
    1062             :                     {
    1063             :                         // emulate data handling from ImpEditEngine::Paint
    1064           0 :                         mpPDFExtOutDevData->BeginStructureElement( vcl::PDFWriter::Paragraph );
    1065             :                     }
    1066             : 
    1067             :                     // process recursively and add MetaFile comment
    1068         714 :                     process(rParagraphPrimitive.get2DDecomposition(getViewInformation2D()));
    1069         714 :                     mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
    1070             : 
    1071         714 :                     if(mpPDFExtOutDevData)
    1072             :                     {
    1073             :                         // emulate data handling from ImpEditEngine::Paint
    1074           0 :                         mpPDFExtOutDevData->EndStructureElement();
    1075             :                     }
    1076             : 
    1077         714 :                     break;
    1078             :                 }
    1079             :                 case PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D :
    1080             :                 {
    1081         662 :                     const primitive2d::TextHierarchyBlockPrimitive2D& rBlockPrimitive = static_cast< const primitive2d::TextHierarchyBlockPrimitive2D& >(rCandidate);
    1082         662 :                     const OString aCommentStringA("XTEXT_PAINTSHAPE_BEGIN");
    1083        1324 :                     const OString aCommentStringB("XTEXT_PAINTSHAPE_END");
    1084             : 
    1085             :                     // add MetaFile comment, process recursively and add MetaFile comment
    1086         662 :                     mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA));
    1087         662 :                     process(rBlockPrimitive.get2DDecomposition(getViewInformation2D()));
    1088         662 :                     mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB));
    1089             : 
    1090        1324 :                     break;
    1091             :                 }
    1092             :                 case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
    1093             :                 case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D :
    1094             :                 {
    1095             :                     // for supporting TEXT_ MetaFile actions there is more to do here; get the candidate
    1096        1008 :                     const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate = static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate);
    1097             :                     // const primitive2d::TextDecoratedPortionPrimitive2D* pTextDecoratedCandidate = dynamic_cast< const primitive2d::TextDecoratedPortionPrimitive2D* >(&rCandidate);
    1098             : 
    1099             :                     // Adapt evtl. used special DrawMode
    1100        1008 :                     const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode());
    1101        1008 :                     adaptTextToFillDrawMode();
    1102             : 
    1103             :                     // directdraw of text simple portion; use default processing
    1104        1008 :                     RenderTextSimpleOrDecoratedPortionPrimitive2D(rTextCandidate);
    1105             : 
    1106             :                     // restore DrawMode
    1107        1008 :                     mpOutputDevice->SetDrawMode(nOriginalDrawMode);
    1108             : 
    1109             :                     // #i101169# if(pTextDecoratedCandidate)
    1110             :                     {
    1111             :                         // support for TEXT_ MetaFile actions only for decorated texts
    1112        1008 :                         if(!mxBreakIterator.is())
    1113             :                         {
    1114          20 :                             uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
    1115          20 :                             mxBreakIterator = i18n::BreakIterator::create(xContext);
    1116             :                         }
    1117             : 
    1118        1008 :                         const OUString& rTxt = rTextCandidate.getText();
    1119        1008 :                         const sal_Int32 nTextLength(rTextCandidate.getTextLength()); // rTxt.getLength());
    1120             : 
    1121        1008 :                         if(nTextLength)
    1122             :                         {
    1123        1008 :                             const ::com::sun::star::lang::Locale& rLocale = rTextCandidate.getLocale();
    1124        1008 :                             const sal_Int32 nTextPosition(rTextCandidate.getTextPosition());
    1125             : 
    1126             :                             sal_Int32 nDone;
    1127        1008 :                             sal_Int32 nNextCellBreak(mxBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone));
    1128        1008 :                             ::com::sun::star::i18n::Boundary nNextWordBoundary(mxBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True));
    1129        1008 :                             sal_Int32 nNextSentenceBreak(mxBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale));
    1130        1008 :                             const OString aCommentStringA("XTEXT_EOC");
    1131        2016 :                             const OString aCommentStringB("XTEXT_EOW");
    1132        2016 :                             const OString aCommentStringC("XTEXT_EOS");
    1133             : 
    1134        9848 :                             for(sal_Int32 i(nTextPosition); i < nTextPosition + nTextLength; i++)
    1135             :                             {
    1136             :                                 // create the entries for the respective break positions
    1137        8840 :                                 if(i == nNextCellBreak)
    1138             :                                 {
    1139        8840 :                                     mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA, i - nTextPosition));
    1140        8840 :                                     nNextCellBreak = mxBreakIterator->nextCharacters(rTxt, i, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
    1141             :                                 }
    1142        8840 :                                 if(i == nNextWordBoundary.endPos)
    1143             :                                 {
    1144         948 :                                     mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB, i - nTextPosition));
    1145         948 :                                     nNextWordBoundary = mxBreakIterator->getWordBoundary(rTxt, i + 1, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True);
    1146             :                                 }
    1147        8840 :                                 if(i == nNextSentenceBreak)
    1148             :                                 {
    1149          48 :                                     mpMetaFile->AddAction(new MetaCommentAction(aCommentStringC, i - nTextPosition));
    1150          48 :                                     nNextSentenceBreak = mxBreakIterator->endOfSentence(rTxt, i + 1, rLocale);
    1151             :                                 }
    1152        1008 :                             }
    1153             :                         }
    1154             :                     }
    1155             : 
    1156        1008 :                     break;
    1157             :                 }
    1158             :                 case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
    1159             :                 {
    1160        3414 :                     const primitive2d::PolygonHairlinePrimitive2D& rHairlinePrimitive = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate);
    1161        3414 :                     const basegfx::B2DPolygon& rBasePolygon = rHairlinePrimitive.getB2DPolygon();
    1162             : 
    1163        3414 :                     if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
    1164             :                     {
    1165             :                         // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
    1166             :                         // per polygon. If there are more, split the polygon in half and call recursively
    1167           0 :                         basegfx::B2DPolygon aLeft, aRight;
    1168           0 :                         splitLinePolygon(rBasePolygon, aLeft, aRight);
    1169           0 :                         const primitive2d::PolygonHairlinePrimitive2D aPLeft(aLeft, rHairlinePrimitive.getBColor());
    1170           0 :                         const primitive2d::PolygonHairlinePrimitive2D aPRight(aRight, rHairlinePrimitive.getBColor());
    1171             : 
    1172           0 :                         processBasePrimitive2D(aPLeft);
    1173           0 :                         processBasePrimitive2D(aPRight);
    1174             :                     }
    1175             :                     else
    1176             :                     {
    1177             :                         // direct draw of hairline; use default processing
    1178             :                         // support SvtGraphicStroke MetaCommentAction
    1179        3414 :                         const basegfx::BColor aLineColor(maBColorModifierStack.getModifiedColor(rHairlinePrimitive.getBColor()));
    1180        3414 :                         SvtGraphicStroke* pSvtGraphicStroke = 0;
    1181             : 
    1182             :                         // #i121267# Not needed, does not give better quality compared with
    1183             :                         // the META_POLYPOLYGON_ACTION written by RenderPolygonHairlinePrimitive2D
    1184             :                         // below
    1185        3414 :                         bool bSupportSvtGraphicStroke(false);
    1186             : 
    1187        3414 :                         if(bSupportSvtGraphicStroke)
    1188             :                         {
    1189             :                             pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
    1190           0 :                                 rHairlinePrimitive.getB2DPolygon(),
    1191             :                                 &aLineColor,
    1192           0 :                                 0, 0, 0, 0);
    1193             : 
    1194           0 :                             impStartSvtGraphicStroke(pSvtGraphicStroke);
    1195             :                         }
    1196             : 
    1197        3414 :                         RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate), false);
    1198             : 
    1199        3414 :                         if(bSupportSvtGraphicStroke)
    1200             :                         {
    1201           0 :                             impEndSvtGraphicStroke(pSvtGraphicStroke);
    1202        3414 :                         }
    1203             :                     }
    1204        3414 :                     break;
    1205             :                 }
    1206             :                 case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D :
    1207             :                 {
    1208        3386 :                     const primitive2d::PolygonStrokePrimitive2D& rStrokePrimitive = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate);
    1209        3386 :                     const basegfx::B2DPolygon& rBasePolygon = rStrokePrimitive.getB2DPolygon();
    1210             : 
    1211        3386 :                     if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
    1212             :                     {
    1213             :                         // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
    1214             :                         // per polygon. If there are more, split the polygon in half and call recursively
    1215           0 :                         basegfx::B2DPolygon aLeft, aRight;
    1216           0 :                         splitLinePolygon(rBasePolygon, aLeft, aRight);
    1217             :                         const primitive2d::PolygonStrokePrimitive2D aPLeft(
    1218           0 :                             aLeft, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute());
    1219             :                         const primitive2d::PolygonStrokePrimitive2D aPRight(
    1220           0 :                             aRight, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute());
    1221             : 
    1222           0 :                         processBasePrimitive2D(aPLeft);
    1223           0 :                         processBasePrimitive2D(aPRight);
    1224             :                     }
    1225             :                     else
    1226             :                     {
    1227             :                         // support SvtGraphicStroke MetaCommentAction
    1228             :                         SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
    1229             :                             rBasePolygon, 0,
    1230        3386 :                             &rStrokePrimitive.getLineAttribute(),
    1231        3386 :                             &rStrokePrimitive.getStrokeAttribute(),
    1232        3386 :                             0, 0);
    1233             : 
    1234        3386 :                         impStartSvtGraphicStroke(pSvtGraphicStroke);
    1235        3386 :                         const attribute::LineAttribute& rLine = rStrokePrimitive.getLineAttribute();
    1236             : 
    1237             :                         // create MetaPolyLineActions, but without LINE_DASH
    1238        3386 :                         if(basegfx::fTools::more(rLine.getWidth(), 0.0))
    1239             :                         {
    1240        1080 :                             const attribute::StrokeAttribute& rStroke = rStrokePrimitive.getStrokeAttribute();
    1241        1080 :                             basegfx::B2DPolyPolygon aHairLinePolyPolygon;
    1242             : 
    1243        1080 :                             if(0.0 == rStroke.getFullDotDashLen())
    1244             :                             {
    1245        1080 :                                 aHairLinePolyPolygon.append(rBasePolygon);
    1246             :                             }
    1247             :                             else
    1248             :                             {
    1249             :                                 basegfx::tools::applyLineDashing(
    1250           0 :                                     rBasePolygon, rStroke.getDotDashArray(),
    1251           0 :                                     &aHairLinePolyPolygon, 0, rStroke.getFullDotDashLen());
    1252             :                             }
    1253             : 
    1254        2160 :                             const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLine.getColor()));
    1255        1080 :                             mpOutputDevice->SetLineColor(Color(aHairlineColor));
    1256        1080 :                             mpOutputDevice->SetFillColor();
    1257        1080 :                             aHairLinePolyPolygon.transform(maCurrentTransformation);
    1258             : 
    1259             :                             // use the transformed line width
    1260        2160 :                             LineInfo aLineInfo(LINE_SOLID, basegfx::fround(getTransformedLineWidth(rLine.getWidth())));
    1261        1080 :                             aLineInfo.SetLineJoin(rLine.getLineJoin());
    1262        1080 :                             aLineInfo.SetLineCap(rLine.getLineCap());
    1263             : 
    1264        2160 :                             for(sal_uInt32 a(0); a < aHairLinePolyPolygon.count(); a++)
    1265             :                             {
    1266        1080 :                                 const basegfx::B2DPolygon aCandidate(aHairLinePolyPolygon.getB2DPolygon(a));
    1267             : 
    1268        1080 :                                 if(aCandidate.count() > 1)
    1269             :                                 {
    1270         572 :                                     const Polygon aToolsPolygon(aCandidate);
    1271             : 
    1272         572 :                                     mpMetaFile->AddAction(new MetaPolyLineAction(aToolsPolygon, aLineInfo));
    1273             :                                 }
    1274        2160 :                             }
    1275             :                         }
    1276             :                         else
    1277             :                         {
    1278        2306 :                             process(rCandidate.get2DDecomposition(getViewInformation2D()));
    1279             :                         }
    1280             : 
    1281        3386 :                         impEndSvtGraphicStroke(pSvtGraphicStroke);
    1282             :                     }
    1283             : 
    1284        3386 :                     break;
    1285             :                 }
    1286             :                 case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D :
    1287             :                 {
    1288          98 :                     const primitive2d::PolygonStrokeArrowPrimitive2D& rStrokeArrowPrimitive = static_cast< const primitive2d::PolygonStrokeArrowPrimitive2D& >(rCandidate);
    1289          98 :                     const basegfx::B2DPolygon& rBasePolygon = rStrokeArrowPrimitive.getB2DPolygon();
    1290             : 
    1291          98 :                     if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
    1292             :                     {
    1293             :                         // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
    1294             :                         // per polygon. If there are more, split the polygon in half and call recursively
    1295           0 :                         basegfx::B2DPolygon aLeft, aRight;
    1296           0 :                         splitLinePolygon(rBasePolygon, aLeft, aRight);
    1297           0 :                         const attribute::LineStartEndAttribute aEmpty;
    1298             :                         const primitive2d::PolygonStrokeArrowPrimitive2D aPLeft(
    1299             :                             aLeft,
    1300           0 :                             rStrokeArrowPrimitive.getLineAttribute(),
    1301           0 :                             rStrokeArrowPrimitive.getStrokeAttribute(),
    1302           0 :                             rStrokeArrowPrimitive.getStart(),
    1303           0 :                             aEmpty);
    1304             :                         const primitive2d::PolygonStrokeArrowPrimitive2D aPRight(
    1305             :                             aRight,
    1306           0 :                             rStrokeArrowPrimitive.getLineAttribute(),
    1307           0 :                             rStrokeArrowPrimitive.getStrokeAttribute(),
    1308             :                             aEmpty,
    1309           0 :                             rStrokeArrowPrimitive.getEnd());
    1310             : 
    1311           0 :                         processBasePrimitive2D(aPLeft);
    1312           0 :                         processBasePrimitive2D(aPRight);
    1313             :                     }
    1314             :                     else
    1315             :                     {
    1316             :                         // support SvtGraphicStroke MetaCommentAction
    1317             :                         SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
    1318             :                             rBasePolygon, 0,
    1319          98 :                             &rStrokeArrowPrimitive.getLineAttribute(),
    1320          98 :                             &rStrokeArrowPrimitive.getStrokeAttribute(),
    1321          98 :                             &rStrokeArrowPrimitive.getStart(),
    1322         196 :                             &rStrokeArrowPrimitive.getEnd());
    1323             : 
    1324             :                         // write LineGeometry start marker
    1325          98 :                         impStartSvtGraphicStroke(pSvtGraphicStroke);
    1326             : 
    1327             :                         // #i116162# When B&W is set as DrawMode, DRAWMODE_WHITEFILL is used
    1328             :                         // to let all fills be just white; for lines DRAWMODE_BLACKLINE is used
    1329             :                         // so all line geometry is supposed to get black. Since in the in-between
    1330             :                         // stages of line geometry drawing filled polygons are used (e.g. line
    1331             :                         // start/ends) it is necessary to change these drawmodes to preserve
    1332             :                         // that lines shall be black; thus change DRAWMODE_WHITEFILL to
    1333             :                         // DRAWMODE_BLACKFILL during line geometry processing to have line geometry
    1334             :                         // parts filled black.
    1335          98 :                         const sal_uLong nOldDrawMode(mpOutputDevice->GetDrawMode());
    1336          98 :                         const bool bDrawmodeChange(nOldDrawMode & DRAWMODE_WHITEFILL && mnSvtGraphicStrokeCount);
    1337             : 
    1338          98 :                         if(bDrawmodeChange)
    1339             :                         {
    1340           0 :                             mpOutputDevice->SetDrawMode((nOldDrawMode & ~DRAWMODE_WHITEFILL) | DRAWMODE_BLACKFILL);
    1341             :                         }
    1342             : 
    1343             :                         // process sub-line geometry (evtl. filled PolyPolygons)
    1344          98 :                         process(rCandidate.get2DDecomposition(getViewInformation2D()));
    1345             : 
    1346          98 :                         if(bDrawmodeChange)
    1347             :                         {
    1348           0 :                             mpOutputDevice->SetDrawMode(nOldDrawMode);
    1349             :                         }
    1350             : 
    1351             :                         // write LineGeometry end marker
    1352          98 :                         impEndSvtGraphicStroke(pSvtGraphicStroke);
    1353             :                     }
    1354             : 
    1355          98 :                     break;
    1356             :                 }
    1357             :                 case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
    1358             :                 {
    1359             :                     // direct draw of transformed BitmapEx primitive; use default processing, but without
    1360             :                     // former testing if graphic content is inside discrete local viewport; this is not
    1361             :                     // setup for metafile targets (metafile renderer tries to render in logic coordinates,
    1362             :                     // the mapping is kept to the OutputDevice for better Metafile recording)
    1363         916 :                     RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
    1364         916 :                     break;
    1365             :                 }
    1366             :                 case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D :
    1367             :                 {
    1368             :                     // need to handle PolyPolygonGraphicPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
    1369          80 :                     const primitive2d::PolyPolygonGraphicPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonGraphicPrimitive2D& >(rCandidate);
    1370          80 :                     basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon());
    1371             : 
    1372          80 :                     if(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
    1373             :                     {
    1374             :                         // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
    1375             :                         // per polygon. If there are more use the splitted polygon and call recursively
    1376             :                         const primitive2d::PolyPolygonGraphicPrimitive2D aSplitted(
    1377             :                             aLocalPolyPolygon,
    1378           0 :                             rBitmapCandidate.getFillGraphic());
    1379             : 
    1380           0 :                         processBasePrimitive2D(aSplitted);
    1381             :                     }
    1382             :                     else
    1383             :                     {
    1384          80 :                         SvtGraphicFill* pSvtGraphicFill = 0;
    1385             : 
    1386          80 :                         if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
    1387             :                         {
    1388             :                             // #121194# Changed implementation and checked usages fo convert to metafile,
    1389             :                             // presentation start (uses SvtGraphicFill) and printing.
    1390             : 
    1391             :                             // calculate transformation. Get real object size, all values in FillGraphicAttribute
    1392             :                             // are relative to the unified object
    1393          80 :                             aLocalPolyPolygon.transform(maCurrentTransformation);
    1394          80 :                             const basegfx::B2DVector aOutlineSize(aLocalPolyPolygon.getB2DRange().getRange());
    1395             : 
    1396             :                             // the scaling needs scale from pixel to logic coordinate system
    1397          80 :                             const attribute::FillGraphicAttribute& rFillGraphicAttribute = rBitmapCandidate.getFillGraphic();
    1398          80 :                             const Size aBmpSizePixel(rFillGraphicAttribute.getGraphic().GetSizePixel());
    1399             : 
    1400             :                             // setup transformation like in impgrfll. Multiply with aOutlineSize
    1401             :                             // to get from unit coordinates in rFillGraphicAttribute.getGraphicRange()
    1402             :                             // to object coordinates with object's top left being at (0,0). Divide
    1403             :                             // by pixel size so that scale from pixel to logic will work in SvtGraphicFill.
    1404             :                             const basegfx::B2DVector aTransformScale(
    1405         240 :                                 rFillGraphicAttribute.getGraphicRange().getRange() /
    1406             :                                 basegfx::B2DVector(
    1407         160 :                                     std::max(1.0, double(aBmpSizePixel.Width())),
    1408         320 :                                     std::max(1.0, double(aBmpSizePixel.Height()))) *
    1409         160 :                                 aOutlineSize);
    1410             :                             const basegfx::B2DPoint aTransformPosition(
    1411         160 :                                 rFillGraphicAttribute.getGraphicRange().getMinimum() * aOutlineSize);
    1412             : 
    1413             :                             // setup transformation like in impgrfll
    1414          80 :                             SvtGraphicFill::Transform aTransform;
    1415             : 
    1416             :                             // scale values are divided by bitmap pixel sizes
    1417          80 :                             aTransform.matrix[0] = aTransformScale.getX();
    1418          80 :                             aTransform.matrix[4] = aTransformScale.getY();
    1419             : 
    1420             :                             // translates are absolute
    1421          80 :                             aTransform.matrix[2] = aTransformPosition.getX();
    1422          80 :                             aTransform.matrix[5] = aTransformPosition.getY();
    1423             : 
    1424             :                             pSvtGraphicFill = new SvtGraphicFill(
    1425             :                                 getFillPolyPolygon(aLocalPolyPolygon),
    1426             :                                 Color(),
    1427             :                                 0.0,
    1428             :                                 SvtGraphicFill::fillEvenOdd,
    1429             :                                 SvtGraphicFill::fillTexture,
    1430             :                                 aTransform,
    1431          80 :                                 rFillGraphicAttribute.getTiling(),
    1432             :                                 SvtGraphicFill::hatchSingle,
    1433             :                                 Color(),
    1434             :                                 SvtGraphicFill::gradientLinear,
    1435             :                                 Color(),
    1436             :                                 Color(),
    1437             :                                 0,
    1438         240 :                                 rFillGraphicAttribute.getGraphic());
    1439             :                         }
    1440             : 
    1441             :                         // Do use decomposition; encapsulate with SvtGraphicFill
    1442          80 :                         impStartSvtGraphicFill(pSvtGraphicFill);
    1443          80 :                         process(rCandidate.get2DDecomposition(getViewInformation2D()));
    1444          80 :                         impEndSvtGraphicFill(pSvtGraphicFill);
    1445             :                     }
    1446             : 
    1447          80 :                     break;
    1448             :                 }
    1449             :                 case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D :
    1450             :                 {
    1451             :                     // need to handle PolyPolygonHatchPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
    1452           2 :                     const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate);
    1453           2 :                     const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch();
    1454           2 :                     basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon());
    1455             : 
    1456           2 :                     if(aLocalPolyPolygon.getB2DRange() != rHatchCandidate.getDefinitionRange())
    1457             :                     {
    1458             :                         // the range which defines the hatch is different from the range of the
    1459             :                         // geometry (used for writer frames). This cannot be done calling vcl, thus use
    1460             :                         // decomposition here
    1461           0 :                         process(rCandidate.get2DDecomposition(getViewInformation2D()));
    1462           0 :                         break;
    1463             :                     }
    1464             : 
    1465             :                     // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
    1466             :                     // per polygon. Split polygon until there are less than that
    1467           2 :                     while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
    1468             :                         ;
    1469             : 
    1470           2 :                     if(rFillHatchAttribute.isFillBackground())
    1471             :                     {
    1472             :                         // with fixing #i111954# (see below) the possible background
    1473             :                         // fill of a hatched object was lost.Generate a background fill
    1474             :                         // primitive and render it
    1475             :                         const primitive2d::Primitive2DReference xBackground(
    1476             :                             new primitive2d::PolyPolygonColorPrimitive2D(
    1477             :                                 aLocalPolyPolygon,
    1478           0 :                                 rHatchCandidate.getBackgroundColor()));
    1479             : 
    1480           0 :                         process(primitive2d::Primitive2DSequence(&xBackground, 1));
    1481             :                     }
    1482             : 
    1483           2 :                     SvtGraphicFill* pSvtGraphicFill = 0;
    1484           2 :                     aLocalPolyPolygon.transform(maCurrentTransformation);
    1485             : 
    1486           2 :                     if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
    1487             :                     {
    1488             :                         // re-create a VCL hatch as base data
    1489           2 :                         SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle);
    1490             : 
    1491           2 :                         switch(rFillHatchAttribute.getStyle())
    1492             :                         {
    1493             :                             default: // attribute::HATCHSTYLE_SINGLE :
    1494             :                             {
    1495           2 :                                 eHatch = SvtGraphicFill::hatchSingle;
    1496           2 :                                 break;
    1497             :                             }
    1498             :                             case attribute::HATCHSTYLE_DOUBLE :
    1499             :                             {
    1500           0 :                                 eHatch = SvtGraphicFill::hatchDouble;
    1501           0 :                                 break;
    1502             :                             }
    1503             :                             case attribute::HATCHSTYLE_TRIPLE :
    1504             :                             {
    1505           0 :                                 eHatch = SvtGraphicFill::hatchTriple;
    1506           0 :                                 break;
    1507             :                             }
    1508             :                         }
    1509             : 
    1510           2 :                         SvtGraphicFill::Transform aTransform;
    1511             : 
    1512             :                         // scale
    1513           2 :                         aTransform.matrix[0] *= rFillHatchAttribute.getDistance();
    1514           2 :                         aTransform.matrix[4] *= rFillHatchAttribute.getDistance();
    1515             : 
    1516             :                         // rotate (was never correct in impgrfll anyways, use correct angle now)
    1517           2 :                         aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle());
    1518           2 :                         aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle());
    1519           2 :                         aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle());
    1520           2 :                         aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle());
    1521             : 
    1522             :                         pSvtGraphicFill = new SvtGraphicFill(
    1523             :                             getFillPolyPolygon(aLocalPolyPolygon),
    1524             :                             Color(),
    1525             :                             0.0,
    1526             :                             SvtGraphicFill::fillEvenOdd,
    1527             :                             SvtGraphicFill::fillHatch,
    1528             :                             aTransform,
    1529             :                             false,
    1530             :                             eHatch,
    1531           2 :                             Color(rFillHatchAttribute.getColor()),
    1532             :                             SvtGraphicFill::gradientLinear,
    1533             :                             Color(),
    1534             :                             Color(),
    1535             :                             0,
    1536           4 :                             Graphic());
    1537             :                     }
    1538             : 
    1539             :                     // Do use decomposition; encapsulate with SvtGraphicFill
    1540           2 :                     impStartSvtGraphicFill(pSvtGraphicFill);
    1541             : 
    1542             :                     // #i111954# do NOT use decomposition, but use direct VCL-command
    1543             :                     // process(rCandidate.get2DDecomposition(getViewInformation2D()));
    1544           2 :                     const tools::PolyPolygon aToolsPolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(aLocalPolyPolygon));
    1545             :                     const HatchStyle aHatchStyle(
    1546           2 :                         attribute::HATCHSTYLE_SINGLE == rFillHatchAttribute.getStyle() ? HATCH_SINGLE :
    1547           0 :                         attribute::HATCHSTYLE_DOUBLE == rFillHatchAttribute.getStyle() ? HATCH_DOUBLE :
    1548           2 :                         HATCH_TRIPLE);
    1549             : 
    1550             :                     mpOutputDevice->DrawHatch(aToolsPolyPolygon,
    1551             :                         Hatch(aHatchStyle,
    1552           2 :                             Color(rFillHatchAttribute.getColor()),
    1553           2 :                             basegfx::fround(rFillHatchAttribute.getDistance()),
    1554           6 :                             basegfx::fround(rFillHatchAttribute.getAngle() / F_PI1800)));
    1555             : 
    1556           2 :                     impEndSvtGraphicFill(pSvtGraphicFill);
    1557             : 
    1558           2 :                     break;
    1559             :                 }
    1560             :                 case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
    1561             :                 {
    1562          32 :                     basegfx::B2DVector aScale, aTranslate;
    1563             :                     double fRotate, fShearX;
    1564             : 
    1565          16 :                     maCurrentTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
    1566             : 
    1567          16 :                     if(!basegfx::fTools::equalZero(fRotate) || !basegfx::fTools::equalZero(fShearX))
    1568             :                     {
    1569             :                         // #i121185# When rotation or shear is used, a VCL Gradient cannot be used directly.
    1570             :                         // This is because VCL Gradient mechanism does *not* support to rotate the gradient
    1571             :                         // with objects and this case is not expressable in a Metafile (and cannot be added
    1572             :                         // since the FileFormats used, e.g. *.wmf, do not support it either).
    1573             :                         // Such cases happen when a graphic object uses a Metafile as graphic information or
    1574             :                         // a fill style definition uses a Metafile. In this cases the graphic content is
    1575             :                         // rotated with the graphic or filled object; this is not supported by the target
    1576             :                         // format of this conversion renderer - Metafiles.
    1577             :                         // To solve this, not a Gradient is written, but the decomposition of this object
    1578             :                         // is written to the Metafile. This is the PolyPolygons building the gradient fill.
    1579             :                         // These will need more space and time, but the result will be as if the Gradient
    1580             :                         // was rotated with the object.
    1581             :                         // This mechanism is used by all exporters still not using Primtives (e.g. Print,
    1582             :                         // Slideshow, Export rto PDF, export to Picture, ...) but relying on Metafile
    1583             :                         // transfers. One more reason to *change* these to primitives.
    1584             :                         // BTW: One more example how useful the principles of primitives are; the decomposition
    1585             :                         // is by definition a simpler, maybe more expensive representation of the same content.
    1586           0 :                         process(rCandidate.get2DDecomposition(getViewInformation2D()));
    1587           0 :                         break;
    1588             :                     }
    1589             : 
    1590          16 :                     const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate);
    1591          32 :                     basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon());
    1592             : 
    1593          16 :                     if(aLocalPolyPolygon.getB2DRange() != rGradientCandidate.getDefinitionRange())
    1594             :                     {
    1595             :                         // the range which defines the gradient is different from the range of the
    1596             :                         // geometry (used for writer frames). This cannot be done calling vcl, thus use
    1597             :                         // decomposition here
    1598           4 :                         process(rCandidate.get2DDecomposition(getViewInformation2D()));
    1599           4 :                         break;
    1600             :                     }
    1601             : 
    1602             :                         // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
    1603             :                         // per polygon. Split polygon until there are less than that
    1604          12 :                         while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
    1605             :                             ;
    1606             : 
    1607             :                         // for support of MetaCommentActions of the form XGRAD_SEQ_BEGIN, XGRAD_SEQ_END
    1608             :                         // it is safest to use the VCL OutputDevice::DrawGradient method which creates those.
    1609             :                         // re-create a VCL-gradient from FillGradientPrimitive2D and the needed tools PolyPolygon
    1610          24 :                         Gradient aVCLGradient;
    1611          12 :                         impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rGradientCandidate.getFillGradient(), false);
    1612          12 :                         aLocalPolyPolygon.transform(maCurrentTransformation);
    1613             : 
    1614             :                         // #i82145# ATM VCL printing of gradients using curved shapes does not work,
    1615             :                         // i submitted the bug with the given ID to THB. When that task is fixed it is
    1616             :                         // necessary to again remove this subdivision since it decreases possible
    1617             :                         // printing quality (not even resolution-dependent for now). THB will tell
    1618             :                         // me when that task is fixed in the master
    1619             :                         const tools::PolyPolygon aToolsPolyPolygon(
    1620             :                             getFillPolyPolygon(
    1621          24 :                                 basegfx::tools::adaptiveSubdivideByAngle(aLocalPolyPolygon)));
    1622             : 
    1623             : 
    1624             :                         // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
    1625          12 :                         SvtGraphicFill* pSvtGraphicFill = 0;
    1626             : 
    1627          12 :                         if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
    1628             :                         {
    1629             :                             // setup gradient stuff like in like in impgrfll
    1630          12 :                             SvtGraphicFill::GradientType eGrad(SvtGraphicFill::gradientLinear);
    1631             : 
    1632          12 :                             switch(aVCLGradient.GetStyle())
    1633             :                             {
    1634             :                                 default : // GradientStyle_LINEAR:
    1635             :                                 case GradientStyle_AXIAL:
    1636          12 :                                     eGrad = SvtGraphicFill::gradientLinear;
    1637          12 :                                     break;
    1638             :                                 case GradientStyle_RADIAL:
    1639             :                                 case GradientStyle_ELLIPTICAL:
    1640           0 :                                     eGrad = SvtGraphicFill::gradientRadial;
    1641           0 :                                     break;
    1642             :                                 case GradientStyle_SQUARE:
    1643             :                                 case GradientStyle_RECT:
    1644           0 :                                     eGrad = SvtGraphicFill::gradientRectangular;
    1645           0 :                                     break;
    1646             :                             }
    1647             : 
    1648             :                         pSvtGraphicFill = new SvtGraphicFill(
    1649             :                             aToolsPolyPolygon,
    1650             :                             Color(),
    1651             :                             0.0,
    1652             :                             SvtGraphicFill::fillEvenOdd,
    1653             :                             SvtGraphicFill::fillGradient,
    1654             :                             SvtGraphicFill::Transform(),
    1655             :                             false,
    1656             :                             SvtGraphicFill::hatchSingle,
    1657             :                             Color(),
    1658             :                             eGrad,
    1659          12 :                             aVCLGradient.GetStartColor(),
    1660          12 :                             aVCLGradient.GetEndColor(),
    1661          12 :                             aVCLGradient.GetSteps(),
    1662          48 :                             Graphic());
    1663             :                     }
    1664             : 
    1665             :                     // call VCL directly; encapsulate with SvtGraphicFill
    1666          12 :                     impStartSvtGraphicFill(pSvtGraphicFill);
    1667          12 :                     mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient);
    1668          12 :                     impEndSvtGraphicFill(pSvtGraphicFill);
    1669             : 
    1670          28 :                     break;
    1671             :                 }
    1672             :                 case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
    1673             :                 {
    1674        2444 :                     const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
    1675        2444 :                     basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
    1676             : 
    1677             :                     // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
    1678             :                     // per polygon. Split polygon until there are less than that
    1679        2444 :                     while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
    1680             :                         ;
    1681             : 
    1682        4888 :                     const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
    1683        2444 :                     aLocalPolyPolygon.transform(maCurrentTransformation);
    1684             : 
    1685             :                     // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
    1686        2444 :                     SvtGraphicFill* pSvtGraphicFill = 0;
    1687             : 
    1688             :                     // #i121267# Not needed, does not give better quality compared with
    1689             :                     // the META_POLYPOLYGON_ACTION written by the DrawPolyPolygon command
    1690             :                     // below
    1691        2444 :                     bool bSupportSvtGraphicFill(false);
    1692             : 
    1693        2444 :                     if(bSupportSvtGraphicFill && !mnSvtGraphicFillCount && aLocalPolyPolygon.count())
    1694             :                     {
    1695             :                         // setup simple color fill stuff like in impgrfll
    1696             :                         pSvtGraphicFill = new SvtGraphicFill(
    1697             :                             getFillPolyPolygon(aLocalPolyPolygon),
    1698             :                             Color(aPolygonColor),
    1699             :                             0.0,
    1700             :                             SvtGraphicFill::fillEvenOdd,
    1701             :                             SvtGraphicFill::fillSolid,
    1702             :                             SvtGraphicFill::Transform(),
    1703             :                             false,
    1704             :                             SvtGraphicFill::hatchSingle,
    1705             :                             Color(),
    1706             :                             SvtGraphicFill::gradientLinear,
    1707             :                             Color(),
    1708             :                             Color(),
    1709             :                             0,
    1710           0 :                             Graphic());
    1711             :                     }
    1712             : 
    1713             :                     // set line and fill color
    1714        2444 :                     mpOutputDevice->SetFillColor(Color(aPolygonColor));
    1715        2444 :                     mpOutputDevice->SetLineColor();
    1716             : 
    1717             :                     // call VCL directly; encapsulate with SvtGraphicFill
    1718        2444 :                     if(bSupportSvtGraphicFill)
    1719             :                     {
    1720           0 :                             impStartSvtGraphicFill(pSvtGraphicFill);
    1721             :                     }
    1722             : 
    1723        2444 :                     mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
    1724             : 
    1725        2444 :                     if(bSupportSvtGraphicFill)
    1726             :                     {
    1727           0 :                         impEndSvtGraphicFill(pSvtGraphicFill);
    1728             :                     }
    1729             : 
    1730        4888 :                     break;
    1731             :                 }
    1732             :                 case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
    1733             :                 {
    1734             :                     static bool bUseMetaFilePrimitiveDecomposition(true);
    1735         158 :                     const primitive2d::MetafilePrimitive2D& aMetafile = static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate);
    1736             : 
    1737         158 :                     if(bUseMetaFilePrimitiveDecomposition && !aMetafile.getMetaFile().GetUseCanvas())
    1738             :                     {
    1739             :                         // Use new Metafile decomposition.
    1740             :                         // TODO EMF+ stuffed into METACOMMENT support required
    1741          82 :                         process(rCandidate.get2DDecomposition(getViewInformation2D()));
    1742             :                     }
    1743             :                     else
    1744             :                     {
    1745             :                         // direct draw of MetaFile, use default processing
    1746          76 :                         RenderMetafilePrimitive2D(aMetafile);
    1747             :                     }
    1748             : 
    1749         158 :                     break;
    1750             :                 }
    1751             :                 case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
    1752             :                 {
    1753             :                     // mask group. Special handling for MetaFiles.
    1754          98 :                     const primitive2d::MaskPrimitive2D& rMaskCandidate = static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate);
    1755             : 
    1756          98 :                     if(rMaskCandidate.getChildren().hasElements())
    1757             :                     {
    1758          98 :                         basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
    1759             : 
    1760          98 :                         if(aMask.count())
    1761             :                         {
    1762             :                             // prepare new mask polygon and rescue current one
    1763          98 :                             aMask.transform(maCurrentTransformation);
    1764          98 :                             const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon);
    1765             : 
    1766          98 :                             if(maClipPolyPolygon.count())
    1767             :                             {
    1768             :                                 // there is already a clip polygon set; build clipped union of
    1769             :                                 // current mask polygon and new one
    1770          12 :                                 maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(
    1771             :                                     aMask,
    1772             :                                     maClipPolyPolygon,
    1773             :                                     true, // #i106516# we want the inside of aMask, not the outside
    1774           6 :                                     false);
    1775             :                             }
    1776             :                             else
    1777             :                             {
    1778             :                                 // use mask directly
    1779          92 :                                 maClipPolyPolygon = aMask;
    1780             :                             }
    1781             : 
    1782          98 :                             if(maClipPolyPolygon.count())
    1783             :                             {
    1784             :                                 // set VCL clip region; subdivide before conversion to tools polygon. Subdivision necessary (!)
    1785             :                                 // Removed subdivision and fixed in vcl::Region::ImplPolyPolyRegionToBandRegionFunc() in VCL where
    1786             :                                 // the ClipRegion is built from the Polygon. A AdaptiveSubdivide on the source polygon was missing there
    1787          98 :                                 mpOutputDevice->Push(PushFlags::CLIPREGION);
    1788          98 :                                 mpOutputDevice->SetClipRegion(vcl::Region(maClipPolyPolygon));
    1789             : 
    1790             :                                 // recursively paint content
    1791             :                                 // #i121267# Only need to process sub-content when clip polygon is *not* empty.
    1792             :                                 // If it is empty, the clip is empty and there can be nothing inside.
    1793          98 :                                 process(rMaskCandidate.getChildren());
    1794             : 
    1795             :                                 // restore VCL clip region
    1796          98 :                                 mpOutputDevice->Pop();
    1797             :                             }
    1798             : 
    1799             :                             // restore to rescued clip polygon
    1800          98 :                             maClipPolyPolygon = aLastClipPolyPolygon;
    1801             :                         }
    1802             :                         else
    1803             :                         {
    1804             :                             // no mask, no clipping. recursively paint content
    1805           0 :                             process(rMaskCandidate.getChildren());
    1806          98 :                         }
    1807             :                     }
    1808             : 
    1809          98 :                     break;
    1810             :                 }
    1811             :                 case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
    1812             :                 {
    1813             :                     // modified color group. Force output to unified color. Use default pocessing.
    1814           0 :                     RenderModifiedColorPrimitive2D(static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate));
    1815           0 :                     break;
    1816             :                 }
    1817             :                 case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D :
    1818             :                 {
    1819             :                     // for metafile: Need to examine what the pure vcl version is doing here actually
    1820             :                     // - uses DrawTransparent with metafile for content and a gradient
    1821             :                     // - uses DrawTransparent for single PolyPoylgons directly. Can be detected by
    1822             :                     //   checking the content for single PolyPolygonColorPrimitive2D
    1823          76 :                     const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate = static_cast< const primitive2d::UnifiedTransparencePrimitive2D& >(rCandidate);
    1824          76 :                     const primitive2d::Primitive2DSequence rContent = rUniTransparenceCandidate.getChildren();
    1825             : 
    1826          76 :                     if(rContent.hasElements())
    1827             :                     {
    1828          76 :                         if(0.0 == rUniTransparenceCandidate.getTransparence())
    1829             :                         {
    1830             :                             // not transparent at all, use content
    1831           0 :                             process(rUniTransparenceCandidate.getChildren());
    1832             :                         }
    1833          76 :                         else if(rUniTransparenceCandidate.getTransparence() > 0.0 && rUniTransparenceCandidate.getTransparence() < 1.0)
    1834             :                         {
    1835             :                             // try to identify a single PolyPolygonColorPrimitive2D in the
    1836             :                             // content part of the transparence primitive
    1837          76 :                             const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = 0;
    1838             :                             static bool bForceToMetafile(false);
    1839             : 
    1840          76 :                             if(!bForceToMetafile && 1 == rContent.getLength())
    1841             :                             {
    1842          76 :                                 const primitive2d::Primitive2DReference xReference(rContent[0]);
    1843          76 :                                 pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get());
    1844             :                             }
    1845             : 
    1846             :                             // PolyPolygonGradientPrimitive2D, PolyPolygonHatchPrimitive2D and
    1847             :                             // PolyPolygonGraphicPrimitive2D are derived from PolyPolygonColorPrimitive2D.
    1848             :                             // Check also for correct ID to exclude derived implementations
    1849          76 :                             if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID())
    1850             :                             {
    1851             :                                 // single transparent tools::PolyPolygon identified, use directly
    1852          76 :                                 const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
    1853         152 :                                 basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon());
    1854             : 
    1855             :                                 // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
    1856             :                                 // per polygon. Split polygon until there are less than that
    1857          76 :                                 while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
    1858             :                                     ;
    1859             : 
    1860             :                                 // now transform
    1861          76 :                                 aLocalPolyPolygon.transform(maCurrentTransformation);
    1862             : 
    1863             :                                 // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
    1864          76 :                                 SvtGraphicFill* pSvtGraphicFill = 0;
    1865             : 
    1866             :                                 // #i121267# Not needed, does not give better quality compared with
    1867             :                                 // the META_POLYPOLYGON_ACTION written by the DrawPolyPolygon command
    1868             :                                 // below
    1869          76 :                                 bool bSupportSvtGraphicFill(false);
    1870             : 
    1871          76 :                                 if(bSupportSvtGraphicFill && !mnSvtGraphicFillCount && aLocalPolyPolygon.count())
    1872             :                                 {
    1873             :                                     // setup simple color with transparence fill stuff like in impgrfll
    1874             :                                     pSvtGraphicFill = new SvtGraphicFill(
    1875             :                                         getFillPolyPolygon(aLocalPolyPolygon),
    1876             :                                         Color(aPolygonColor),
    1877             :                                         rUniTransparenceCandidate.getTransparence(),
    1878             :                                         SvtGraphicFill::fillEvenOdd,
    1879             :                                         SvtGraphicFill::fillSolid,
    1880             :                                         SvtGraphicFill::Transform(),
    1881             :                                         false,
    1882             :                                         SvtGraphicFill::hatchSingle,
    1883             :                                         Color(),
    1884             :                                         SvtGraphicFill::gradientLinear,
    1885             :                                         Color(),
    1886             :                                         Color(),
    1887             :                                         0,
    1888           0 :                                         Graphic());
    1889             :                                 }
    1890             : 
    1891             :                                 // set line and fill color
    1892          76 :                                 const sal_uInt16 nTransPercentVcl((sal_uInt16)basegfx::fround(rUniTransparenceCandidate.getTransparence() * 100.0));
    1893          76 :                                 mpOutputDevice->SetFillColor(Color(aPolygonColor));
    1894          76 :                                 mpOutputDevice->SetLineColor();
    1895             : 
    1896             :                                 // call VCL directly; encapsulate with SvtGraphicFill
    1897          76 :                                 if(bSupportSvtGraphicFill)
    1898             :                                 {
    1899           0 :                                     impStartSvtGraphicFill(pSvtGraphicFill);
    1900             :                                 }
    1901             : 
    1902             :                                 mpOutputDevice->DrawTransparent(
    1903             :                                     tools::PolyPolygon(aLocalPolyPolygon),
    1904          76 :                                     nTransPercentVcl);
    1905             : 
    1906          76 :                                 if(bSupportSvtGraphicFill)
    1907             :                                 {
    1908           0 :                                     impEndSvtGraphicFill(pSvtGraphicFill);
    1909          76 :                                 }
    1910             :                             }
    1911             :                             else
    1912             :                             {
    1913             :                                 // svae old mfCurrentUnifiedTransparence and set new one
    1914             :                                 // so that contained SvtGraphicStroke may use the current one
    1915           0 :                                 const double fLastCurrentUnifiedTransparence(mfCurrentUnifiedTransparence);
    1916             :                                 // #i105377# paint the content metafile opaque as the transparency gets
    1917             :                                 // split of into the gradient below
    1918             :                                 // mfCurrentUnifiedTransparence = rUniTransparenceCandidate.getTransparence();
    1919           0 :                                 mfCurrentUnifiedTransparence = 0;
    1920             : 
    1921             :                                 // various content, create content-metafile
    1922           0 :                                 GDIMetaFile aContentMetafile;
    1923           0 :                                 const Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile));
    1924             : 
    1925             :                                 // restore mfCurrentUnifiedTransparence; it may have been used
    1926             :                                 // while processing the sub-content in impDumpToMetaFile
    1927           0 :                                 mfCurrentUnifiedTransparence = fLastCurrentUnifiedTransparence;
    1928             : 
    1929             :                                 // create uniform VCL gradient for uniform transparency
    1930           0 :                                 Gradient aVCLGradient;
    1931           0 :                                 const sal_uInt8 nTransPercentVcl((sal_uInt8)basegfx::fround(rUniTransparenceCandidate.getTransparence() * 255.0));
    1932           0 :                                 const Color aTransColor(nTransPercentVcl, nTransPercentVcl, nTransPercentVcl);
    1933             : 
    1934           0 :                                 aVCLGradient.SetStyle(GradientStyle_LINEAR);
    1935           0 :                                 aVCLGradient.SetStartColor(aTransColor);
    1936           0 :                                 aVCLGradient.SetEndColor(aTransColor);
    1937           0 :                                 aVCLGradient.SetAngle(0);
    1938           0 :                                 aVCLGradient.SetBorder(0);
    1939           0 :                                 aVCLGradient.SetOfsX(0);
    1940           0 :                                 aVCLGradient.SetOfsY(0);
    1941           0 :                                 aVCLGradient.SetStartIntensity(100);
    1942           0 :                                 aVCLGradient.SetEndIntensity(100);
    1943           0 :                                 aVCLGradient.SetSteps(2);
    1944             : 
    1945             :                                 // render it to VCL
    1946             :                                 mpOutputDevice->DrawTransparent(
    1947             :                                     aContentMetafile, aPrimitiveRectangle.TopLeft(),
    1948           0 :                                     aPrimitiveRectangle.GetSize(), aVCLGradient);
    1949             :                             }
    1950             :                         }
    1951             :                     }
    1952             : 
    1953          76 :                     break;
    1954             :                 }
    1955             :                 case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D :
    1956             :                 {
    1957             :                     // for metafile: Need to examine what the pure vcl version is doing here actually
    1958             :                     // - uses DrawTransparent with metafile for content and a gradient
    1959             :                     // i can detect this here with checking the gradient part for a single
    1960             :                     // FillGradientPrimitive2D and reconstruct the gradient.
    1961             :                     // If that detection goes wrong, i have to create an transparence-blended bitmap. Eventually
    1962             :                     // do that in stripes, else RenderTransparencePrimitive2D may just be used
    1963           0 :                     const primitive2d::TransparencePrimitive2D& rTransparenceCandidate = static_cast< const primitive2d::TransparencePrimitive2D& >(rCandidate);
    1964           0 :                     const primitive2d::Primitive2DSequence rContent = rTransparenceCandidate.getChildren();
    1965           0 :                     const primitive2d::Primitive2DSequence rTransparence = rTransparenceCandidate.getTransparence();
    1966             : 
    1967           0 :                     if(rContent.hasElements() && rTransparence.hasElements())
    1968             :                     {
    1969             :                         // try to identify a single FillGradientPrimitive2D in the
    1970             :                         // transparence part of the primitive
    1971           0 :                         const primitive2d::FillGradientPrimitive2D* pFiGradient = 0;
    1972             :                         static bool bForceToBigTransparentVDev(false);
    1973             : 
    1974           0 :                         if(!bForceToBigTransparentVDev && 1 == rTransparence.getLength())
    1975             :                         {
    1976           0 :                             const primitive2d::Primitive2DReference xReference(rTransparence[0]);
    1977           0 :                             pFiGradient = dynamic_cast< const primitive2d::FillGradientPrimitive2D* >(xReference.get());
    1978             :                         }
    1979             : 
    1980             :                         // Check also for correct ID to exclude derived implementations
    1981           0 :                         if(pFiGradient && PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D == pFiGradient->getPrimitive2DID())
    1982             :                         {
    1983             :                             // various content, create content-metafile
    1984           0 :                             GDIMetaFile aContentMetafile;
    1985           0 :                             const Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile));
    1986             : 
    1987             :                             // re-create a VCL-gradient from FillGradientPrimitive2D
    1988           0 :                             Gradient aVCLGradient;
    1989           0 :                             impConvertFillGradientAttributeToVCLGradient(aVCLGradient, pFiGradient->getFillGradient(), true);
    1990             : 
    1991             :                             // render it to VCL
    1992             :                             mpOutputDevice->DrawTransparent(
    1993             :                                 aContentMetafile, aPrimitiveRectangle.TopLeft(),
    1994           0 :                                 aPrimitiveRectangle.GetSize(), aVCLGradient);
    1995             :                         }
    1996             :                         else
    1997             :                         {
    1998             :                             // sub-transparence group. Draw to VDev first.
    1999             :                             // this may get refined to tiling when resolution is too big here
    2000             : 
    2001             :                             // need to avoid switching off MapMode stuff here; maybe need another
    2002             :                             // tooling class, cannot just do the same as with the pixel renderer.
    2003             :                             // Need to experiment...
    2004             : 
    2005             :                             // Okay, basic implementation finished and tested. The DPI stuff was hard
    2006             :                             // and not easy to find out that it's needed.
    2007             :                             // Since this will not yet happen normally (as long as no one constructs
    2008             :                             // transparence primitives with non-trivial transparence content) i will for now not
    2009             :                             // refine to tiling here.
    2010             : 
    2011           0 :                             basegfx::B2DRange aViewRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
    2012           0 :                             aViewRange.transform(maCurrentTransformation);
    2013             :                             const Rectangle aRectLogic(
    2014           0 :                                 (sal_Int32)floor(aViewRange.getMinX()), (sal_Int32)floor(aViewRange.getMinY()),
    2015           0 :                                 (sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY()));
    2016           0 :                             const Rectangle aRectPixel(mpOutputDevice->LogicToPixel(aRectLogic));
    2017           0 :                             Size aSizePixel(aRectPixel.GetSize());
    2018           0 :                             const Point aEmptyPoint;
    2019           0 :                             VirtualDevice aBufferDevice;
    2020           0 :                             const sal_uInt32 nMaxQuadratPixels(500000);
    2021           0 :                             const sal_uInt32 nViewVisibleArea(aSizePixel.getWidth() * aSizePixel.getHeight());
    2022           0 :                             double fReduceFactor(1.0);
    2023             : 
    2024           0 :                             if(nViewVisibleArea > nMaxQuadratPixels)
    2025             :                             {
    2026             :                                 // reduce render size
    2027           0 :                                 fReduceFactor = sqrt((double)nMaxQuadratPixels / (double)nViewVisibleArea);
    2028           0 :                                 aSizePixel = Size(basegfx::fround((double)aSizePixel.getWidth() * fReduceFactor),
    2029           0 :                                     basegfx::fround((double)aSizePixel.getHeight() * fReduceFactor));
    2030             :                             }
    2031             : 
    2032           0 :                             if(aBufferDevice.SetOutputSizePixel(aSizePixel))
    2033             :                             {
    2034             :                                 // create and set MapModes for target devices
    2035           0 :                                 MapMode aNewMapMode(mpOutputDevice->GetMapMode());
    2036           0 :                                 aNewMapMode.SetOrigin(Point(-aRectLogic.Left(), -aRectLogic.Top()));
    2037           0 :                                 aBufferDevice.SetMapMode(aNewMapMode);
    2038             : 
    2039             :                                 // prepare view transformation for target renderers
    2040             :                                 // ATTENTION! Need to apply another scaling because of the potential DPI differences
    2041             :                                 // between Printer and VDev (mpOutputDevice and aBufferDevice here).
    2042             :                                 // To get the DPI, LogicToPixel from (1,1) from MAP_INCH needs to be used.
    2043           0 :                                 basegfx::B2DHomMatrix aViewTransform(aBufferDevice.GetViewTransformation());
    2044           0 :                                 const Size aDPIOld(mpOutputDevice->LogicToPixel(Size(1, 1), MAP_INCH));
    2045           0 :                                 const Size aDPINew(aBufferDevice.LogicToPixel(Size(1, 1), MAP_INCH));
    2046           0 :                                 const double fDPIXChange((double)aDPIOld.getWidth() / (double)aDPINew.getWidth());
    2047           0 :                                 const double fDPIYChange((double)aDPIOld.getHeight() / (double)aDPINew.getHeight());
    2048             : 
    2049           0 :                                 if(!basegfx::fTools::equal(fDPIXChange, 1.0) || !basegfx::fTools::equal(fDPIYChange, 1.0))
    2050             :                                 {
    2051           0 :                                     aViewTransform.scale(fDPIXChange, fDPIYChange);
    2052             :                                 }
    2053             : 
    2054             :                                 // also take scaling from Size reduction into acount
    2055           0 :                                 if(!basegfx::fTools::equal(fReduceFactor, 1.0))
    2056             :                                 {
    2057           0 :                                     aViewTransform.scale(fReduceFactor, fReduceFactor);
    2058             :                                 }
    2059             : 
    2060             :                                 // create view information and pixel renderer. Reuse known ViewInformation
    2061             :                                 // except new transformation and range
    2062             :                                 const geometry::ViewInformation2D aViewInfo(
    2063           0 :                                     getViewInformation2D().getObjectTransformation(),
    2064             :                                     aViewTransform,
    2065             :                                     aViewRange,
    2066           0 :                                     getViewInformation2D().getVisualizedPage(),
    2067           0 :                                     getViewInformation2D().getViewTime(),
    2068           0 :                                     getViewInformation2D().getExtendedInformationSequence());
    2069             : 
    2070           0 :                                 VclPixelProcessor2D aBufferProcessor(aViewInfo, aBufferDevice);
    2071             : 
    2072             :                                 // draw content using pixel renderer
    2073           0 :                                 aBufferProcessor.process(rContent);
    2074           0 :                                 const Bitmap aBmContent(aBufferDevice.GetBitmap(aEmptyPoint, aSizePixel));
    2075             : 
    2076             :                                 // draw transparence using pixel renderer
    2077           0 :                                 aBufferDevice.Erase();
    2078           0 :                                 aBufferProcessor.process(rTransparence);
    2079           0 :                                 const AlphaMask aBmAlpha(aBufferDevice.GetBitmap(aEmptyPoint, aSizePixel));
    2080             : 
    2081             :                                 // paint
    2082             :                                 mpOutputDevice->DrawBitmapEx(
    2083             :                                     aRectLogic.TopLeft(),
    2084             :                                     aRectLogic.GetSize(),
    2085           0 :                                     BitmapEx(aBmContent, aBmAlpha));
    2086           0 :                             }
    2087             :                         }
    2088             :                     }
    2089             : 
    2090           0 :                     break;
    2091             :                 }
    2092             :                 case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
    2093             :                 {
    2094             :                     // use default transform group pocessing
    2095         748 :                     RenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
    2096         748 :                     break;
    2097             :                 }
    2098             :                 case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
    2099             :                 {
    2100             :                     // new XDrawPage for ViewInformation2D
    2101           0 :                     RenderPagePreviewPrimitive2D(static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate));
    2102           0 :                     break;
    2103             :                 }
    2104             :                 case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
    2105             :                 {
    2106             :                     // use default marker array pocessing
    2107           0 :                     RenderMarkerArrayPrimitive2D(static_cast< const primitive2d::MarkerArrayPrimitive2D& >(rCandidate));
    2108           0 :                     break;
    2109             :                 }
    2110             :                 case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
    2111             :                 {
    2112             :                     // use default point array pocessing
    2113           0 :                     RenderPointArrayPrimitive2D(static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate));
    2114           0 :                     break;
    2115             :                 }
    2116             :                 case PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D :
    2117             :                 {
    2118             :                     // structured tag primitive
    2119           0 :                     const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate = static_cast< const primitive2d::StructureTagPrimitive2D& >(rCandidate);
    2120           0 :                     const vcl::PDFWriter::StructElement& rTagElement(rStructureTagCandidate.getStructureElement());
    2121           0 :                     const bool bTagUsed(vcl::PDFWriter::NonStructElement != rTagElement);
    2122             : 
    2123           0 :                     if(mpPDFExtOutDevData &&  bTagUsed)
    2124             :                     {
    2125             :                         // write start tag
    2126           0 :                         mpPDFExtOutDevData->BeginStructureElement(rTagElement);
    2127             :                     }
    2128             : 
    2129             :                     // process children normally
    2130           0 :                     process(rStructureTagCandidate.getChildren());
    2131             : 
    2132           0 :                     if(mpPDFExtOutDevData &&  bTagUsed)
    2133             :                     {
    2134             :                         // write end tag
    2135           0 :                         mpPDFExtOutDevData->EndStructureElement();
    2136             :                     }
    2137             : 
    2138           0 :                     break;
    2139             :                 }
    2140             :                 case PRIMITIVE2D_ID_EPSPRIMITIVE2D :
    2141             :                 {
    2142           0 :                     RenderEpsPrimitive2D(static_cast< const primitive2d::EpsPrimitive2D& >(rCandidate));
    2143           0 :                     break;
    2144             :                 }
    2145             :                 case PRIMITIVE2D_ID_OPENGLPRIMITIVE2D:
    2146             :                 {
    2147           0 :                     RenderOpenGLPrimitive2D(static_cast< const primitive2d::OpenGLPrimitive2D& >(rCandidate));
    2148           0 :                     break;
    2149             :                 }
    2150             :                 default :
    2151             :                 {
    2152             :                     // process recursively
    2153        9180 :                     process(rCandidate.get2DDecomposition(getViewInformation2D()));
    2154        9180 :                     break;
    2155             :                 }
    2156             :             }
    2157       24084 :         }
    2158             :     } // end of namespace processor2d
    2159        1143 : } // end of namespace drawinglayer
    2160             : 
    2161             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10