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

Generated by: LCOV version 1.10