LCOV - code coverage report
Current view: top level - cppcanvas/source/mtfrenderer - emfplus.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 896 0.0 %
Date: 2014-04-14 Functions: 0 49 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <tools/stream.hxx>
      21             : #include <vcl/metaact.hxx>
      22             : #include <vcl/graphicfilter.hxx>
      23             : #include <basegfx/tools/canvastools.hxx>
      24             : #include <basegfx/tools/gradienttools.hxx>
      25             : #include <basegfx/tools/tools.hxx>
      26             : #include <basegfx/numeric/ftools.hxx>
      27             : #include <basegfx/point/b2dpoint.hxx>
      28             : #include <basegfx/vector/b2dsize.hxx>
      29             : #include <basegfx/range/b2drange.hxx>
      30             : #include <basegfx/range/b2drectangle.hxx>
      31             : #include <basegfx/polygon/b2dlinegeometry.hxx>
      32             : #include <basegfx/polygon/b2dpolygon.hxx>
      33             : #include <basegfx/polygon/b2dpolygontools.hxx>
      34             : #include <basegfx/polygon/b2dpolypolygon.hxx>
      35             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      36             : #include <vcl/canvastools.hxx>
      37             : #include <rtl/ustring.hxx>
      38             : #include <sal/alloca.h>
      39             : 
      40             : #include <com/sun/star/rendering/PathCapType.hpp>
      41             : #include <com/sun/star/rendering/PathJoinType.hpp>
      42             : #include <com/sun/star/rendering/TexturingMode.hpp>
      43             : #include <com/sun/star/rendering/XCanvas.hpp>
      44             : 
      45             : #include <bitmapaction.hxx>
      46             : #include <implrenderer.hxx>
      47             : #include <outdevstate.hxx>
      48             : #include <polypolyaction.hxx>
      49             : #include <textaction.hxx>
      50             : #include <stdio.h>
      51             : 
      52             : #define EmfPlusRecordTypeHeader 16385
      53             : #define EmfPlusRecordTypeEndOfFile 16386
      54             : #define EmfPlusRecordTypeGetDC 16388
      55             : #define EmfPlusRecordTypeObject 16392
      56             : #define EmfPlusRecordTypeFillRects 16394
      57             : #define EmfPlusRecordTypeFillPolygon 16396
      58             : #define EmfPlusRecordTypeDrawLines 16397
      59             : #define EmfPlusRecordTypeFillEllipse 16398
      60             : #define EmfPlusRecordTypeDrawEllipse 16399
      61             : #define EmfPlusRecordTypeFillPie 16400
      62             : #define EmfPlusRecordTypeFillPath 16404
      63             : #define EmfPlusRecordTypeDrawPath 16405
      64             : #define EmfPlusRecordTypeDrawImage 16410
      65             : #define EmfPlusRecordTypeDrawImagePoints 16411
      66             : #define EmfPlusRecordTypeDrawString 16412
      67             : #define EmfPlusRecordTypeSetRenderingOrigin 16413
      68             : #define EmfPlusRecordTypeSetAntiAliasMode 16414
      69             : #define EmfPlusRecordTypeSetTextRenderingHint 16415
      70             : #define EmfPlusRecordTypeSetInterpolationMode 16417
      71             : #define EmfPlusRecordTypeSetPixelOffsetMode 16418
      72             : #define EmfPlusRecordTypeSetCompositingQuality 16420
      73             : #define EmfPlusRecordTypeSave 16421
      74             : #define EmfPlusRecordTypeRestore 16422
      75             : #define EmfPlusRecordTypeBeginContainerNoParams 16424
      76             : #define EmfPlusRecordTypeEndContainer 16425
      77             : #define EmfPlusRecordTypeSetWorldTransform 16426
      78             : #define EmfPlusRecordTypeResetWorldTransform 16427
      79             : #define EmfPlusRecordTypeMultiplyWorldTransform 16428
      80             : #define EmfPlusRecordTypeSetPageTransform 16432
      81             : #define EmfPlusRecordTypeSetClipRect 16434
      82             : #define EmfPlusRecordTypeSetClipPath 16435
      83             : #define EmfPlusRecordTypeSetClipRegion 16436
      84             : #define EmfPlusRecordTypeDrawDriverString 16438
      85             : 
      86             : #define EmfPlusObjectTypeBrush 0x100
      87             : #define EmfPlusObjectTypePen 0x200
      88             : #define EmfPlusObjectTypePath 0x300
      89             : #define EmfPlusObjectTypeRegion 0x400
      90             : #define EmfPlusObjectTypeImage 0x500
      91             : #define EmfPlusObjectTypeFont 0x600
      92             : 
      93             : #define EmfPlusRegionInitialStateInfinite 0x10000003
      94             : 
      95             : const sal_Int32 EmfPlusLineStyleSolid = 0x00000000;
      96             : const sal_Int32 EmfPlusLineStyleDash = 0x00000001;
      97             : const sal_Int32 EmfPlusLineStyleDot = 0x00000002;
      98             : const sal_Int32 EmfPlusLineStyleDashDot = 0x00000003;
      99             : const sal_Int32 EmfPlusLineStyleDashDotDot = 0x00000004;
     100             : const sal_Int32 EmfPlusLineStyleCustom = 0x00000005;
     101             : 
     102             : const sal_uInt32 EmfPlusCustomLineCapDataTypeDefault = 0x00000000;
     103             : const sal_uInt32 EmfPlusCustomLineCapDataTypeAdjustableArrow = 0x00000001;
     104             : 
     105             : const sal_uInt32 EmfPlusCustomLineCapDataFillPath = 0x00000001;
     106             : const sal_uInt32 EmfPlusCustomLineCapDataLinePath = 0x00000002;
     107             : 
     108             : const sal_uInt32 EmfPlusLineCapTypeSquare = 0x00000001;
     109             : const sal_uInt32 EmfPlusLineCapTypeRound = 0x00000002;
     110             : 
     111             : const sal_uInt32 EmfPlusLineJoinTypeMiter = 0x00000000;
     112             : const sal_uInt32 EmfPlusLineJoinTypeBevel = 0x00000001;
     113             : const sal_uInt32 EmfPlusLineJoinTypeRound = 0x00000002;
     114             : const sal_uInt32 EmfPlusLineJoinTypeMiterClipped = 0x00000003;
     115             : 
     116             : enum EmfPlusCombineMode
     117             : {
     118             :     EmfPlusCombineModeReplace = 0x00000000,
     119             :     EmfPlusCombineModeIntersect = 0x00000001,
     120             :     EmfPlusCombineModeUnion = 0x00000002,
     121             :     EmfPlusCombineModeXOR = 0x00000003,
     122             :     EmfPlusCombineModeExclude = 0x00000004,
     123             :     EmfPlusCombineModeComplement = 0x00000005
     124             : };
     125             : 
     126             : using namespace ::com::sun::star;
     127             : using namespace ::basegfx;
     128             : 
     129             : namespace cppcanvas
     130             : {
     131             :     namespace internal
     132             :     {
     133             :         struct EMFPPath : public EMFPObject
     134             :         {
     135             :             ::basegfx::B2DPolyPolygon    aPolygon;
     136             :             sal_Int32                    nPoints;
     137             :             float*                       pPoints;
     138             :             sal_uInt8*                   pPointTypes;
     139             : 
     140             :         public:
     141           0 :             EMFPPath (sal_Int32 _nPoints, bool bLines = false)
     142           0 :             {
     143           0 :                 if( _nPoints<0 || sal_uInt32(_nPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
     144           0 :                     _nPoints = SAL_MAX_INT32/(2*sizeof(float));
     145           0 :                 nPoints = _nPoints;
     146           0 :                 pPoints = new float [nPoints*2];
     147           0 :                 if (!bLines)
     148           0 :                     pPointTypes = new sal_uInt8 [_nPoints];
     149             :                 else
     150           0 :                     pPointTypes = NULL;
     151           0 :             }
     152             : 
     153           0 :             virtual ~EMFPPath ()
     154           0 :             {
     155           0 :                 delete [] pPoints;
     156           0 :                 delete [] pPointTypes;
     157           0 :             }
     158             : 
     159             :             // TODO: remove rR argument when debug code is not longer needed
     160           0 :             void Read (SvStream& s, sal_uInt32 pathFlags, ImplRenderer& rR)
     161             :             {
     162           0 :                 for (int i = 0; i < nPoints; i ++) {
     163           0 :                     if (pathFlags & 0x4000) {
     164             :                         // EMFPlusPoint: stored in signed short 16bit integer format
     165             :                         sal_Int16 x, y;
     166             : 
     167           0 :                         s.ReadInt16( x ).ReadInt16( y );
     168             :                         SAL_INFO ("cppcanvas.emf", "EMF+\tEMFPlusPoint [x,y]: " << x << "," << y);
     169           0 :                         pPoints [i*2] = x;
     170           0 :                         pPoints [i*2 + 1] = y;
     171           0 :                     } else if (!(pathFlags & 0xC000)) {
     172             :                         // EMFPlusPointF: stored in Single (float) format
     173           0 :                         s.ReadFloat( pPoints [i*2] ).ReadFloat( pPoints [i*2 + 1] );
     174             :                         SAL_INFO ("cppcanvas.emf", "EMF+\tEMFPlusPointF [x,y]: " << pPoints [i*2] << "," << pPoints [i*2 + 1]);
     175             :                     } else { //if (pathFlags & 0x8000)
     176             :                         // EMFPlusPointR: points are stored in EMFPlusInteger7 or
     177             :                         // EMFPlusInteger15 objects, see section 2.2.2.21/22
     178             :                         SAL_INFO("cppcanvas.emf", "EMF+\t\tTODO - parse EMFPlusPointR object (section 2.2.1.6)");
     179             :                     }
     180             : 
     181             :                 }
     182             : 
     183           0 :                 if (pPointTypes)
     184           0 :                     for (int i = 0; i < nPoints; i ++) {
     185           0 :                         s.ReadUChar( pPointTypes [i] );
     186             :                         SAL_INFO ("cppcanvas.emf", "EMF+\tpoint type: " << (int)pPointTypes [i]);
     187             :                     }
     188             : 
     189           0 :                 aPolygon.clear ();
     190             : 
     191             : #if OSL_DEBUG_LEVEL > 1
     192             :                 const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (GetPolygon (rR)));
     193             : 
     194             :                 SAL_INFO ("cppcanvas.emf",
     195             :                           "EMF+\tpolygon bounding box: " << aBounds.getMinX () << "," << aBounds.getMinY () << aBounds.getWidth () << "x" << aBounds.getHeight () << " (mapped)");
     196             : #else
     197             :                 (void) rR; // avoid warnings
     198             : #endif
     199           0 :             }
     200             : 
     201           0 :             ::basegfx::B2DPolyPolygon& GetPolygon (ImplRenderer& rR, bool bMapIt = true)
     202             :             {
     203           0 :                 ::basegfx::B2DPolygon polygon;
     204             : 
     205           0 :                 aPolygon.clear ();
     206             : 
     207           0 :                 int last_normal = 0, p = 0;
     208           0 :                 ::basegfx::B2DPoint prev, mapped;
     209           0 :                 bool hasPrev = false;
     210           0 :                 for (int i = 0; i < nPoints; i ++) {
     211           0 :                     if (p && pPointTypes && (pPointTypes [i] == 0)) {
     212           0 :                         aPolygon.append (polygon);
     213           0 :                         last_normal = i;
     214           0 :                         p = 0;
     215           0 :                         polygon.clear ();
     216             :                     }
     217             : 
     218           0 :                     if (bMapIt)
     219           0 :                         mapped = rR.Map (pPoints [i*2], pPoints [i*2 + 1]);
     220             :                     else
     221           0 :                         mapped = ::basegfx::B2DPoint (pPoints [i*2], pPoints [i*2 + 1]);
     222           0 :                     if (pPointTypes) {
     223           0 :                         if ((pPointTypes [i] & 0x07) == 3) {
     224           0 :                             if (((i - last_normal )% 3) == 1) {
     225           0 :                                 polygon.setNextControlPoint (p - 1, mapped);
     226             :                                 SAL_INFO ("cppcanvas.emf", "polygon append  next: " << p - 1 << " mapped: " << mapped.getX () << "," << mapped.getY ());
     227           0 :                                 continue;
     228           0 :                             } else if (((i - last_normal) % 3) == 2) {
     229           0 :                                 prev = mapped;
     230           0 :                                 hasPrev = true;
     231           0 :                                 continue;
     232             :                             }
     233             :                         } else
     234           0 :                             last_normal = i;
     235             :                     }
     236           0 :                     polygon.append (mapped);
     237             :                     SAL_INFO ("cppcanvas.emf", "polygon append point: " << pPoints [i*2] << "," << pPoints [i*2 + 1] << " mapped: " << mapped.getX () << ":" << mapped.getY ());
     238           0 :                     if (hasPrev) {
     239           0 :                         polygon.setPrevControlPoint (p, prev);
     240             :                         SAL_INFO ("cppcanvas.emf", "polygon append  prev: " << p << " mapped: " << prev.getX () << "," << prev.getY ());
     241           0 :                         hasPrev = false;
     242             :                     }
     243           0 :                     p ++;
     244           0 :                     if (pPointTypes && (pPointTypes [i] & 0x80)) { // closed polygon
     245           0 :                         polygon.setClosed (true);
     246           0 :                         aPolygon.append (polygon);
     247             :                         SAL_INFO ("cppcanvas.emf", "close polygon");
     248           0 :                         last_normal = i + 1;
     249           0 :                         p = 0;
     250           0 :                         polygon.clear ();
     251             :                     }
     252             :                 }
     253             : 
     254           0 :                 if (polygon.count ()) {
     255           0 :                     aPolygon.append (polygon);
     256             : 
     257             : #if OSL_DEBUG_LEVEL > 1
     258             :                     for (unsigned int i=0; i<aPolygon.count(); i++) {
     259             :                         polygon = aPolygon.getB2DPolygon(i);
     260             :                         SAL_INFO ("cppcanvas.emf", "polygon: " << i);
     261             :                         for (unsigned int j=0; j<polygon.count(); j++) {
     262             :                             ::basegfx::B2DPoint point = polygon.getB2DPoint(j);
     263             :                             SAL_INFO ("cppcanvas.emf", "point: " << point.getX() << "," << point.getY());
     264             :                             if (polygon.isPrevControlPointUsed(j)) {
     265             :                                 point = polygon.getPrevControlPoint(j);
     266             :                                 SAL_INFO ("cppcanvas.emf", "prev: " << point.getX() << "," << point.getY());
     267             :                             }
     268             :                             if (polygon.isNextControlPointUsed(j)) {
     269             :                                 point = polygon.getNextControlPoint(j);
     270             :                                 SAL_INFO ("cppcanvas.emf", "next: " << point.getX() << "," << point.getY());
     271             :                             }
     272             :                         }
     273             :                     }
     274             : #endif
     275             :                 }
     276             : 
     277           0 :                 return aPolygon;
     278             :             }
     279             :         };
     280             : 
     281             :         struct EMFPRegion : public EMFPObject
     282             :         {
     283             :             sal_Int32 parts;
     284             :             sal_Int32 *combineMode;
     285             :             sal_Int32 initialState;
     286             :             EMFPPath *initialPath;
     287             :             float ix, iy, iw, ih;
     288             : 
     289           0 :             EMFPRegion ()
     290           0 :             {
     291           0 :                 combineMode = NULL;
     292           0 :                 initialPath = NULL;
     293           0 :             }
     294             : 
     295           0 :             virtual ~EMFPRegion ()
     296           0 :             {
     297           0 :                 if (combineMode) {
     298           0 :                     delete [] combineMode;
     299           0 :                     combineMode = NULL;
     300             :                 }
     301           0 :                 if (initialPath) {
     302           0 :                     delete initialPath;
     303           0 :                     initialPath = NULL;
     304             :                 }
     305           0 :             }
     306             : 
     307           0 :             void Read (SvStream& s)
     308             :             {
     309             :                 sal_uInt32 header;
     310             : 
     311           0 :                 s.ReadUInt32( header ).ReadInt32( parts );
     312             : 
     313             :                 SAL_INFO ("cppcanvas.emf", "EMF+\tregion");
     314             :                 SAL_INFO ("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " parts: " << parts << std::dec );
     315             : 
     316           0 :                 if (parts) {
     317           0 :                     if( parts<0 || sal_uInt32(parts)>SAL_MAX_INT32/sizeof(sal_Int32) )
     318           0 :                         parts = SAL_MAX_INT32/sizeof(sal_Int32);
     319             : 
     320           0 :                     combineMode = new sal_Int32 [parts];
     321             : 
     322           0 :                     for (int i = 0; i < parts; i ++) {
     323           0 :                         s.ReadInt32( combineMode [i] );
     324             :                         SAL_INFO ("cppcanvas.emf", "EMF+\tcombine mode [" << i << "]: 0x" << std::hex << combineMode [i] << std::dec);
     325             :                     }
     326             :                 }
     327             : 
     328           0 :                 s.ReadInt32( initialState );
     329             :                 SAL_INFO ("cppcanvas.emf", "EMF+\tinitial state: 0x" << std::hex << initialState << std::dec);
     330           0 :             }
     331             :         };
     332             : 
     333             :         struct EMFPBrush : public EMFPObject
     334             :         {
     335             :             ::Color solidColor;
     336             :             sal_uInt32 type;
     337             :             sal_uInt32 additionalFlags;
     338             : 
     339             :             /* linear gradient */
     340             :             sal_Int32 wrapMode;
     341             :             float areaX, areaY, areaWidth, areaHeight;
     342             :             ::Color secondColor; // first color is stored in solidColor;
     343             :             XForm transformation;
     344             :             bool hasTransformation;
     345             :             sal_Int32 blendPoints;
     346             :             float* blendPositions;
     347             :             float* blendFactors;
     348             :             sal_Int32 colorblendPoints;
     349             :             float* colorblendPositions;
     350             :             ::Color* colorblendColors;
     351             :             sal_Int32 surroundColorsNumber;
     352             :             ::Color* surroundColors;
     353             :             EMFPPath *path;
     354             : 
     355             :         public:
     356           0 :             EMFPBrush ()
     357           0 :             {
     358           0 :                 blendPositions = NULL;
     359           0 :                 colorblendPositions = NULL;
     360           0 :                 colorblendColors = NULL;
     361           0 :                 surroundColors = NULL;
     362           0 :                 path = NULL;
     363           0 :                 hasTransformation = false;
     364           0 :             }
     365             : 
     366           0 :             virtual ~EMFPBrush ()
     367           0 :             {
     368           0 :                 if (blendPositions != NULL) {
     369           0 :                     delete[] blendPositions;
     370           0 :                     blendPositions = NULL;
     371             :                 }
     372           0 :                 if (colorblendPositions != NULL) {
     373           0 :                     delete[] colorblendPositions;
     374           0 :                     colorblendPositions = NULL;
     375             :                 }
     376           0 :                 if (colorblendColors != NULL) {
     377           0 :                     delete[] colorblendColors;
     378           0 :                     colorblendColors = NULL;
     379             :                 }
     380           0 :                 if (surroundColors != NULL) {
     381           0 :                     delete[] surroundColors;
     382           0 :                     surroundColors = NULL;
     383             :                 }
     384           0 :                 if (path) {
     385           0 :                     delete path;
     386           0 :                     path = NULL;
     387             :                 }
     388           0 :             }
     389             : 
     390             :             sal_uInt32 GetType() const { return type; }
     391           0 :             const ::Color& GetColor() const { return solidColor; }
     392             : 
     393           0 :             void Read (SvStream& s, ImplRenderer& rR)
     394             :             {
     395             :                 sal_uInt32 header;
     396             : 
     397           0 :                 s.ReadUInt32( header ).ReadUInt32( type );
     398             : 
     399             :                 SAL_INFO ("cppcanvas.emf", "EMF+\tbrush");
     400             :                 SAL_INFO ("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec);
     401             : 
     402           0 :                 switch (type) {
     403             :                 case 0:
     404             :                     {
     405             :                         sal_uInt32 color;
     406             : 
     407           0 :                         s.ReadUInt32( color );
     408           0 :                         solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
     409             :                         SAL_INFO ("cppcanvas.emf", "EMF+\tsolid color: 0x" << std::hex << color << std::dec);
     410             : 
     411           0 :                         break;
     412             :                     }
     413             :                 // path gradient
     414             :                 case 3:
     415             :                     {
     416           0 :                         s.ReadUInt32( additionalFlags ).ReadInt32( wrapMode );
     417             : 
     418             :                         SAL_INFO ("cppcanvas.emf", "EMF+\tpath gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec);
     419             : 
     420             :                         sal_uInt32 color;
     421             : 
     422           0 :                         s.ReadUInt32( color );
     423           0 :                         solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
     424             :                         SAL_INFO("cppcanvas.emf", "EMF+\tcenter color: 0x" << std::hex << color << std::dec);
     425             : 
     426           0 :                         s.ReadFloat( areaX ).ReadFloat( areaY );
     427             :                         SAL_INFO("cppcanvas.emf", "EMF+\tcenter point: " << areaX << "," << areaY);
     428             : 
     429           0 :                         s.ReadInt32( surroundColorsNumber );
     430             :                         SAL_INFO("cppcanvas.emf", "EMF+\tsurround colors: " << surroundColorsNumber);
     431             : 
     432           0 :                         if( surroundColorsNumber<0 || sal_uInt32(surroundColorsNumber)>SAL_MAX_INT32/sizeof(::Color) )
     433           0 :                             surroundColorsNumber = SAL_MAX_INT32/sizeof(::Color);
     434             : 
     435           0 :                         surroundColors = new ::Color [surroundColorsNumber];
     436           0 :                         for (int i = 0; i < surroundColorsNumber; i++) {
     437           0 :                             s.ReadUInt32( color );
     438           0 :                             surroundColors[i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
     439           0 :                             if (i == 0)
     440           0 :                                 secondColor = surroundColors [0];
     441             :                             SAL_INFO("cppcanvas.emf", "EMF+\tsurround color[" << i << "]: 0x" << std::hex << color << std::dec);
     442             :                         }
     443             : 
     444           0 :                         if (additionalFlags & 0x01) {
     445             :                             sal_Int32 pathLength;
     446             : 
     447           0 :                             s.ReadInt32( pathLength );
     448             :                             SAL_INFO("cppcanvas.emf", "EMF+\tpath length: " << pathLength);
     449             : 
     450           0 :                             sal_Size pos = s.Tell ();
     451             : 
     452             :                             sal_uInt32 pathHeader;
     453             :                             sal_Int32 pathPoints, pathFlags;
     454           0 :                             s.ReadUInt32( pathHeader ).ReadInt32( pathPoints ).ReadInt32( pathFlags );
     455             : 
     456             :                             SAL_INFO("cppcanvas.emf", "EMF+\tpath (brush path gradient)");
     457             :                             SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec );
     458             : 
     459           0 :                             path = new EMFPPath (pathPoints);
     460           0 :                             path->Read (s, pathFlags, rR);
     461             : 
     462           0 :                             s.Seek (pos + pathLength);
     463             : 
     464           0 :                             const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (path->GetPolygon (rR, false)));
     465           0 :                             areaWidth = aBounds.getWidth ();
     466           0 :                             areaHeight = aBounds.getHeight ();
     467             : 
     468             :                             SAL_INFO("cppcanvas.emf", "EMF+\tpolygon bounding box: " << aBounds.getMinX () << "," << aBounds.getMinY () << " " << aBounds.getWidth () << "x" << aBounds.getHeight ());
     469             : 
     470             : 
     471           0 :                         if (additionalFlags & 0x02) {
     472             :                             SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation");
     473           0 :                             ReadXForm( s, transformation );
     474           0 :                             hasTransformation = true;
     475             :                             SAL_INFO("cppcanvas.emf",
     476             :                                     "EMF+\tm11: "   << transformation.eM11 << " m12: " << transformation.eM12 <<
     477             :                                     "\nEMF+\tm21: " << transformation.eM21 << " m22: " << transformation.eM22 <<
     478             :                                     "\nEMF+\tdx: "  << transformation.eDx  << " dy: "  << transformation.eDy);
     479             : 
     480             :                         }
     481           0 :                         if (additionalFlags & 0x08) {
     482           0 :                             s.ReadInt32( blendPoints );
     483             :                             SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints);
     484           0 :                             if( blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
     485           0 :                                 blendPoints = SAL_MAX_INT32/(2*sizeof(float));
     486           0 :                             blendPositions = new float [2*blendPoints];
     487           0 :                             blendFactors = blendPositions + blendPoints;
     488           0 :                             for (int i=0; i < blendPoints; i ++) {
     489           0 :                                 s.ReadFloat( blendPositions [i] );
     490             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions [i]);
     491             :                             }
     492           0 :                             for (int i=0; i < blendPoints; i ++) {
     493           0 :                                 s.ReadFloat( blendFactors [i] );
     494             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors [i]);
     495             :                             }
     496             :                         }
     497             : 
     498           0 :                         if (additionalFlags & 0x04) {
     499           0 :                             s.ReadInt32( colorblendPoints );
     500             :                             SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints);
     501           0 :                             if( colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(float) )
     502           0 :                                 colorblendPoints = SAL_MAX_INT32/sizeof(float);
     503           0 :                             if( sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(::Color) )
     504           0 :                                 colorblendPoints = SAL_MAX_INT32/sizeof(::Color);
     505           0 :                             colorblendPositions = new float [colorblendPoints];
     506           0 :                             colorblendColors = new ::Color [colorblendPoints];
     507           0 :                             for (int i=0; i < colorblendPoints; i ++) {
     508           0 :                                 s.ReadFloat( colorblendPositions [i] );
     509             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions [i]);
     510             :                             }
     511           0 :                             for (int i=0; i < colorblendPoints; i ++) {
     512           0 :                                 s.ReadUInt32( color );
     513           0 :                                 colorblendColors [i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
     514             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec);
     515             :                             }
     516             :                         }
     517             :                         }
     518           0 :                         break;
     519             :                     }
     520             :                 // linear gradient
     521             :                 case 4:
     522             :                     {
     523           0 :                         s.ReadUInt32( additionalFlags ).ReadInt32( wrapMode );
     524             : 
     525             :                         SAL_INFO("cppcanvas.emf", "EMF+\tlinear gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec);
     526             : 
     527           0 :                         s.ReadFloat( areaX ).ReadFloat( areaY ).ReadFloat( areaWidth ).ReadFloat( areaHeight );
     528             : 
     529             :                         SAL_INFO("cppcanvas.emf", "EMF+\tarea: " << areaX << "," << areaY << " - " << areaWidth << "x" << areaHeight);
     530             : 
     531             :                         sal_uInt32 color;
     532             : 
     533           0 :                         s.ReadUInt32( color );
     534           0 :                         solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
     535             :                         SAL_INFO("cppcanvas.emf", "EMF+\tfirst color: 0x" << std::hex << color << std::dec);
     536             : 
     537           0 :                         s.ReadUInt32( color );
     538           0 :                         secondColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
     539             :                         SAL_INFO("cppcanvas.emf", "EMF+\tsecond color: 0x" << std::hex << color << std::dec);
     540             : 
     541             :                         // repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html
     542           0 :                         s.ReadUInt32( color );
     543           0 :                         s.ReadUInt32( color );
     544             : 
     545           0 :                         if (additionalFlags & 0x02) {
     546             :                             SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation");
     547           0 :                             ReadXForm( s, transformation );
     548           0 :                             hasTransformation = true;
     549             :                             SAL_INFO("cppcanvas.emf",
     550             :                                     "EMF+\tm11: "   << transformation.eM11 << " m12: " << transformation.eM12 <<
     551             :                                     "\nEMF+\tm21: " << transformation.eM21 << " m22: " << transformation.eM22 <<
     552             :                                     "\nEMF+\tdx: "  << transformation.eDx  << " dy: "  << transformation.eDy);
     553             :                         }
     554           0 :                         if (additionalFlags & 0x08) {
     555           0 :                             s.ReadInt32( blendPoints );
     556             :                             SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints);
     557           0 :                             if( blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
     558           0 :                                 blendPoints = SAL_MAX_INT32/(2*sizeof(float));
     559           0 :                             blendPositions = new float [2*blendPoints];
     560           0 :                             blendFactors = blendPositions + blendPoints;
     561           0 :                             for (int i=0; i < blendPoints; i ++) {
     562           0 :                                 s.ReadFloat( blendPositions [i] );
     563             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions [i]);
     564             :                             }
     565           0 :                             for (int i=0; i < blendPoints; i ++) {
     566           0 :                                 s.ReadFloat( blendFactors [i] );
     567             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors [i]);
     568             :                             }
     569             :                         }
     570             : 
     571           0 :                         if (additionalFlags & 0x04) {
     572           0 :                             s.ReadInt32( colorblendPoints );
     573             :                             SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints);
     574           0 :                             if( colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(float) )
     575           0 :                                 colorblendPoints = SAL_MAX_INT32/sizeof(float);
     576           0 :                             if( sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(::Color) )
     577           0 :                                 colorblendPoints = sal_uInt32(SAL_MAX_INT32)/sizeof(::Color);
     578           0 :                             colorblendPositions = new float [colorblendPoints];
     579           0 :                             colorblendColors = new ::Color [colorblendPoints];
     580           0 :                             for (int i=0; i < colorblendPoints; i ++) {
     581           0 :                                 s.ReadFloat( colorblendPositions [i] );
     582             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions [i]);
     583             :                             }
     584           0 :                             for (int i=0; i < colorblendPoints; i ++) {
     585           0 :                                 s.ReadUInt32( color );
     586           0 :                                 colorblendColors [i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
     587             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec);
     588             :                             }
     589             :                         }
     590             : 
     591           0 :                         break;
     592             :                     }
     593             :                 default:
     594             :                     SAL_INFO("cppcanvas.emf", "EMF+\tunhandled brush type: " << std::hex << type << std::dec);
     595             :                 }
     596           0 :             }
     597             :         };
     598             : 
     599             :         /// Convert stroke caps between EMF+ and rendering API
     600           0 :         sal_Int8 lcl_convertStrokeCap(sal_uInt32 nEmfStroke)
     601             :         {
     602           0 :             switch (nEmfStroke)
     603             :             {
     604           0 :                 case EmfPlusLineCapTypeSquare: return rendering::PathCapType::SQUARE;
     605           0 :                 case EmfPlusLineCapTypeRound:  return rendering::PathCapType::ROUND;
     606             :             }
     607             : 
     608             :             // we have no mapping for EmfPlusLineCapTypeTriangle = 0x00000003,
     609             :             // so return BUTT always
     610           0 :             return rendering::PathCapType::BUTT;
     611             :         }
     612             : 
     613           0 :         sal_Int8 lcl_convertLineJoinType(sal_uInt32 nEmfLineJoin)
     614             :         {
     615           0 :             switch (nEmfLineJoin)
     616             :             {
     617             :                 case EmfPlusLineJoinTypeMiter:        // fall-through
     618           0 :                 case EmfPlusLineJoinTypeMiterClipped: return rendering::PathJoinType::MITER;
     619           0 :                 case EmfPlusLineJoinTypeBevel:        return rendering::PathJoinType::BEVEL;
     620           0 :                 case EmfPlusLineJoinTypeRound:        return rendering::PathJoinType::ROUND;
     621             :             }
     622             :             assert(false); // Line Join type isn't in specification.
     623           0 :             return 0;
     624             :         }
     625             : 
     626             :         struct EMFPCustomLineCap : public EMFPObject
     627             :         {
     628             :             sal_uInt32 type;
     629             :             sal_uInt32 strokeStartCap, strokeEndCap, strokeJoin;
     630             :             float miterLimit;
     631             :             basegfx::B2DPolyPolygon polygon;
     632             :             bool mbIsFilled;
     633             : 
     634             :         public:
     635           0 :             EMFPCustomLineCap()
     636             :                 : EMFPObject()
     637             :                 , type(0)
     638             :                 , strokeStartCap(0)
     639             :                 , strokeEndCap(0)
     640             :                 , strokeJoin(0)
     641             :                 , miterLimit(0.0)
     642           0 :                 , mbIsFilled(false)
     643             :             {
     644           0 :             }
     645             : 
     646           0 :             virtual ~EMFPCustomLineCap()
     647           0 :             {
     648           0 :             }
     649             : 
     650           0 :             void SetAttributes(rendering::StrokeAttributes& aAttributes)
     651             :             {
     652           0 :                 aAttributes.StartCapType = lcl_convertStrokeCap(strokeStartCap);
     653           0 :                 aAttributes.EndCapType = lcl_convertStrokeCap(strokeEndCap);
     654           0 :                 aAttributes.JoinType = lcl_convertLineJoinType(strokeJoin);
     655             : 
     656           0 :                 aAttributes.MiterLimit = miterLimit;
     657           0 :             }
     658             : 
     659           0 :             void ReadPath(SvStream& s, ImplRenderer& rR, bool bFill)
     660             :             {
     661             :                 sal_Int32 pathLength;
     662           0 :                 s.ReadInt32( pathLength );
     663             :                 SAL_INFO("cppcanvas.emf", "EMF+\t\tpath length: " << pathLength);
     664             : 
     665             :                 sal_uInt32 pathHeader;
     666             :                 sal_Int32 pathPoints, pathFlags;
     667           0 :                 s.ReadUInt32( pathHeader ).ReadInt32( pathPoints ).ReadInt32( pathFlags );
     668             : 
     669             :                 SAL_INFO("cppcanvas.emf", "EMF+\t\tpath (custom cap line path)");
     670             :                 SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec );
     671             : 
     672           0 :                 EMFPPath path(pathPoints);
     673           0 :                 path.Read(s, pathFlags, rR);
     674             : 
     675           0 :                 polygon = path.GetPolygon(rR, false);
     676           0 :                 mbIsFilled = bFill;
     677             : 
     678             :                 // transformation to convert the path to what LibreOffice
     679             :                 // expects
     680           0 :                 B2DHomMatrix aMatrix;
     681           0 :                 aMatrix.scale(1.0, -1.0);
     682             : 
     683           0 :                 polygon.transform(aMatrix);
     684           0 :             };
     685             : 
     686           0 :             void Read (SvStream& s, ImplRenderer& rR)
     687             :             {
     688             :                 sal_uInt32 header;
     689             : 
     690           0 :                 s.ReadUInt32( header ).ReadUInt32( type );
     691             : 
     692             :                 SAL_INFO("cppcanvas.emf", "EMF+\t\tcustom cap");
     693             :                 SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << header << " type: " << type << std::dec);
     694             : 
     695           0 :                 if (type == EmfPlusCustomLineCapDataTypeDefault)
     696             :                 {
     697             :                     sal_uInt32 customLineCapDataFlags, baseCap;
     698             :                     float baseInset;
     699             :                     float widthScale;
     700             :                     float fillHotSpotX, fillHotSpotY, strokeHotSpotX, strokeHotSpotY;
     701             : 
     702           0 :                     s.ReadUInt32( customLineCapDataFlags ).ReadUInt32( baseCap ).ReadFloat( baseInset )
     703           0 :                      .ReadUInt32( strokeStartCap ).ReadUInt32( strokeEndCap ).ReadUInt32( strokeJoin )
     704           0 :                      .ReadFloat( miterLimit ).ReadFloat( widthScale )
     705           0 :                      .ReadFloat( fillHotSpotX ).ReadFloat( fillHotSpotY ).ReadFloat( strokeHotSpotX ).ReadFloat( strokeHotSpotY );
     706             : 
     707             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomLineCapDataFlags: 0x" << std::hex << customLineCapDataFlags);
     708             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tbaseCap: 0x" << std::hex << baseCap);
     709             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tbaseInset: " << baseInset);
     710             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeStartCap: 0x" << std::hex << strokeStartCap);
     711             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeEndCap: 0x" << std::hex << strokeEndCap);
     712             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeJoin: 0x" << std::hex << strokeJoin);
     713             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tmiterLimit: " << miterLimit);
     714             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\twidthScale: " << widthScale);
     715             : 
     716           0 :                     if (customLineCapDataFlags & EmfPlusCustomLineCapDataFillPath)
     717             :                     {
     718           0 :                         ReadPath(s, rR, true);
     719             :                     }
     720             : 
     721           0 :                     if (customLineCapDataFlags & EmfPlusCustomLineCapDataLinePath)
     722             :                     {
     723           0 :                         ReadPath(s, rR, false);
     724             :                     }
     725             :                 }
     726           0 :                 else if (type == EmfPlusCustomLineCapDataTypeAdjustableArrow)
     727             :                 {
     728             :                     // TODO only reads the data, does not use them [I've had
     729             :                     // no test document to be able to implement it]
     730             : 
     731             :                     sal_Int32 width, height, middleInset, fillState, lineStartCap;
     732             :                     sal_Int32 lineEndCap, lineJoin, widthScale;
     733             :                     float fillHotSpotX, fillHotSpotY, lineHotSpotX, lineHotSpotY;
     734             : 
     735           0 :                     s.ReadInt32( width ).ReadInt32( height ).ReadInt32( middleInset ).ReadInt32( fillState ).ReadInt32( lineStartCap )
     736           0 :                      .ReadInt32( lineEndCap ).ReadInt32( lineJoin ).ReadFloat( miterLimit ).ReadInt32( widthScale )
     737           0 :                      .ReadFloat( fillHotSpotX ).ReadFloat( fillHotSpotY ).ReadFloat( lineHotSpotX ).ReadFloat( lineHotSpotY );
     738             : 
     739             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tTODO - actually read EmfPlusCustomLineCapArrowData object (section 2.2.2.12)");
     740             :                 }
     741           0 :             }
     742             :         };
     743             : 
     744             :         struct EMFPPen : public EMFPBrush
     745             :         {
     746             :             XForm transformation;
     747             :             float width;
     748             :             sal_Int32 startCap;
     749             :             sal_Int32 endCap;
     750             :             sal_Int32 lineJoin;
     751             :             float mitterLimit;
     752             :             sal_Int32 dashStyle;
     753             :             sal_Int32 dashCap;
     754             :             float dashOffset;
     755             :             sal_Int32 dashPatternLen;
     756             :             float *dashPattern;
     757             :             sal_Int32 alignment;
     758             :             sal_Int32 compoundArrayLen;
     759             :             float *compoundArray;
     760             :             sal_Int32 customStartCapLen;
     761             :             EMFPCustomLineCap *customStartCap;
     762             :             sal_Int32 customEndCapLen;
     763             :             EMFPCustomLineCap *customEndCap;
     764             : 
     765             :         public:
     766           0 :             EMFPPen () : EMFPBrush ()
     767             :             {
     768           0 :                 dashPattern = NULL;
     769           0 :                 compoundArray = NULL;
     770           0 :                 customStartCap = NULL;
     771           0 :                 customEndCap = NULL;
     772           0 :             }
     773             : 
     774           0 :             virtual ~EMFPPen ()
     775           0 :             {
     776           0 :                 delete[] dashPattern;
     777           0 :                 delete[] compoundArray;
     778           0 :                 delete customStartCap;
     779           0 :                 delete customEndCap;
     780           0 :             }
     781             : 
     782           0 :             void SetStrokeWidth(rendering::StrokeAttributes& rStrokeAttributes, ImplRenderer& rR, const OutDevState& rState)
     783             :             {
     784             : #if OSL_DEBUG_LEVEL > 1
     785             :                 if (width == 0.0) {
     786             :                     SAL_INFO ("cppcanvas.emf", "TODO: pen with zero width - using minimal which might not be correct\n");
     787             :                 }
     788             : #endif
     789           0 :                 rStrokeAttributes.StrokeWidth = fabs((rState.mapModeTransform * rR.MapSize (width == 0.0 ? 0.05 : width, 0)).getLength());
     790           0 :             }
     791             : 
     792           0 :             void SetStrokeAttributes(rendering::StrokeAttributes& rStrokeAttributes)
     793             :             {
     794           0 :                 rStrokeAttributes.JoinType = lcl_convertLineJoinType(lineJoin);
     795             : 
     796           0 :                 if (dashStyle != EmfPlusLineStyleSolid)
     797             :                 {
     798           0 :                     const float dash[] = {3, 3};
     799           0 :                     const float dot[] = {1, 3};
     800           0 :                     const float dashdot[] = {3, 3, 1, 3};
     801           0 :                     const float dashdotdot[] = {3, 3, 1, 3, 1, 3};
     802             : 
     803           0 :                     sal_Int32 nLen = 0;
     804           0 :                     const float *pPattern = NULL;
     805           0 :                     switch (dashStyle)
     806             :                     {
     807           0 :                         case EmfPlusLineStyleDash:       nLen = SAL_N_ELEMENTS(dash); pPattern = dash; break;
     808           0 :                         case EmfPlusLineStyleDot:        nLen = SAL_N_ELEMENTS(dot); pPattern = dot; break;
     809           0 :                         case EmfPlusLineStyleDashDot:    nLen = SAL_N_ELEMENTS(dashdot); pPattern = dashdot; break;
     810           0 :                         case EmfPlusLineStyleDashDotDot: nLen = SAL_N_ELEMENTS(dashdotdot); pPattern = dashdotdot; break;
     811           0 :                         case EmfPlusLineStyleCustom:     nLen = dashPatternLen; pPattern = dashPattern; break;
     812             :                     }
     813           0 :                     if (nLen > 0)
     814             :                     {
     815           0 :                         uno::Sequence<double> aDashArray(nLen);
     816           0 :                         for (int i = 0; i < nLen; ++i)
     817           0 :                             aDashArray[i] = pPattern[i];
     818             : 
     819           0 :                         rStrokeAttributes.DashArray = aDashArray;
     820             :                     }
     821             :                 }
     822           0 :             }
     823             : 
     824           0 :             void Read (SvStream& s, ImplRenderer& rR, sal_Int32, sal_Int32 )
     825             :             {
     826             :                 sal_uInt32 header, unknown, penFlags, unknown2;
     827             :                 int i;
     828             : 
     829           0 :                 s.ReadUInt32( header ).ReadUInt32( unknown ).ReadUInt32( penFlags ).ReadUInt32( unknown2 ).ReadFloat( width );
     830             : 
     831             :                 SAL_INFO("cppcanvas.emf", "EMF+\tpen");
     832             :                 SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " unknown: 0x" << unknown <<
     833             :                             " additional flags: 0x" << penFlags << " unknown: 0x" << unknown2 << " width: " << std::dec << width );
     834             : 
     835           0 :                 if (penFlags & 1)
     836           0 :                     ReadXForm( s, transformation );
     837             : 
     838           0 :                 if (penFlags & 2)
     839             :                 {
     840           0 :                     s.ReadInt32( startCap );
     841             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tstartCap: 0x" << std::hex << startCap);
     842             :                 }
     843             :                 else
     844           0 :                     startCap = 0;
     845             : 
     846           0 :                 if (penFlags & 4)
     847             :                 {
     848           0 :                     s.ReadInt32( endCap );
     849             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tendCap: 0x" << std::hex << endCap);
     850             :                 }
     851             :                 else
     852           0 :                     endCap = 0;
     853             : 
     854           0 :                 if (penFlags & 8)
     855           0 :                     s.ReadInt32( lineJoin );
     856             :                 else
     857           0 :                     lineJoin = 0;
     858             : 
     859           0 :                 if (penFlags & 16)
     860           0 :                     s.ReadFloat( mitterLimit );
     861             :                 else
     862           0 :                     mitterLimit = 0;
     863             : 
     864           0 :                 if (penFlags & 32)
     865             :                 {
     866           0 :                     s.ReadInt32( dashStyle );
     867             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tdashStyle: 0x" << std::hex << dashStyle);
     868             :                 }
     869             :                 else
     870           0 :                     dashStyle = 0;
     871             : 
     872           0 :                 if (penFlags & 64)
     873           0 :                     s.ReadInt32( dashCap );
     874             :                 else
     875           0 :                     dashCap = 0;
     876             : 
     877           0 :                 if (penFlags & 128)
     878           0 :                     s.ReadFloat( dashOffset );
     879             :                 else
     880           0 :                     dashOffset = 0;
     881             : 
     882           0 :                 if (penFlags & 256)
     883             :                 {
     884           0 :                     dashStyle = EmfPlusLineStyleCustom;
     885             : 
     886           0 :                     s.ReadInt32( dashPatternLen );
     887             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tdashPatternLen: " << dashPatternLen);
     888             : 
     889           0 :                     if( dashPatternLen<0 || sal_uInt32(dashPatternLen)>SAL_MAX_INT32/sizeof(float) )
     890           0 :                         dashPatternLen = SAL_MAX_INT32/sizeof(float);
     891           0 :                     dashPattern = new float [dashPatternLen];
     892           0 :                     for (i = 0; i < dashPatternLen; i++)
     893             :                     {
     894           0 :                         s.ReadFloat( dashPattern [i] );
     895             :                         SAL_INFO("cppcanvas.emf", "EMF+\t\t\tdashPattern[" << i << "]: " << dashPattern[i]);
     896             :                     }
     897             :                 }
     898             :                 else
     899           0 :                     dashPatternLen = 0;
     900             : 
     901           0 :                 if (penFlags & 512)
     902           0 :                     s.ReadInt32( alignment );
     903             :                 else
     904           0 :                     alignment = 0;
     905             : 
     906           0 :                 if (penFlags & 1024) {
     907           0 :                     s.ReadInt32( compoundArrayLen );
     908           0 :                     if( compoundArrayLen<0 || sal_uInt32(compoundArrayLen)>SAL_MAX_INT32/sizeof(float) )
     909           0 :                         compoundArrayLen = SAL_MAX_INT32/sizeof(float);
     910           0 :                     compoundArray = new float [compoundArrayLen];
     911           0 :                     for (i = 0; i < compoundArrayLen; i++)
     912           0 :                         s.ReadFloat( compoundArray [i] );
     913             :                 } else
     914           0 :                     compoundArrayLen = 0;
     915             : 
     916           0 :                 if (penFlags & 2048)
     917             :                 {
     918           0 :                     s.ReadInt32( customStartCapLen );
     919             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomStartCapLen: " << customStartCapLen);
     920           0 :                     sal_Size pos = s.Tell();
     921             : 
     922           0 :                     customStartCap = new EMFPCustomLineCap();
     923           0 :                     customStartCap->Read(s, rR);
     924             : 
     925             :                     // maybe we don't read everything yet, play it safe ;-)
     926           0 :                     s.Seek(pos + customStartCapLen);
     927             :                 }
     928             :                 else
     929           0 :                     customStartCapLen = 0;
     930             : 
     931           0 :                 if (penFlags & 4096)
     932             :                 {
     933           0 :                     s.ReadInt32( customEndCapLen );
     934             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomEndCapLen: " << customEndCapLen);
     935           0 :                     sal_Size pos = s.Tell();
     936             : 
     937           0 :                     customEndCap = new EMFPCustomLineCap();
     938           0 :                     customEndCap->Read(s, rR);
     939             : 
     940             :                     // maybe we don't read everything yet, play it safe ;-)
     941           0 :                     s.Seek(pos + customEndCapLen);
     942             :                 }
     943             :                 else
     944           0 :                     customEndCapLen = 0;
     945             : 
     946           0 :                 EMFPBrush::Read (s, rR);
     947           0 :             }
     948             :         };
     949             : 
     950           0 :         struct EMFPImage : public EMFPObject
     951             :         {
     952             :             sal_uInt32 type;
     953             :             sal_Int32 width;
     954             :             sal_Int32 height;
     955             :             sal_Int32 stride;
     956             :             sal_Int32 pixelFormat;
     957             :             Graphic graphic;
     958             : 
     959             : 
     960           0 :             void Read (SvMemoryStream &s, sal_uInt32 dataSize, bool bUseWholeStream)
     961             :             {
     962             :                 sal_uInt32 header, unknown;
     963             : 
     964           0 :                 s.ReadUInt32( header ).ReadUInt32( type );
     965             : 
     966             :                 SAL_INFO("cppcanvas.emf", "EMF+\timage\nEMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec );
     967             : 
     968           0 :                 if (type == 1) { // bitmap
     969           0 :                     s.ReadInt32( width ).ReadInt32( height ).ReadInt32( stride ).ReadInt32( pixelFormat ).ReadUInt32( unknown );
     970             :                     SAL_INFO("cppcanvas.emf", "EMF+\tbitmap width: " << width << " height: " << height << " stride: " << stride << " pixelFormat: 0x" << std::hex << pixelFormat << std::dec);
     971           0 :                     if (width == 0) { // non native formats
     972           0 :                         GraphicFilter filter;
     973             : 
     974           0 :                         filter.ImportGraphic (graphic, OUString(), s);
     975           0 :                         SAL_INFO("cppcanvas.emf", "EMF+\tbitmap width: "  << graphic.GetBitmap().GetSizePixel().Width() << " height: " << graphic.GetBitmap().GetSizePixel().Height());
     976             :                     }
     977             : 
     978           0 :                 } else if (type == 2) {
     979             :                     sal_Int32 mfType, mfSize;
     980             : 
     981           0 :                     s.ReadInt32( mfType ).ReadInt32( mfSize );
     982             :                     SAL_INFO("cppcanvas.emf", "EMF+\tmetafile type: " << mfType << " dataSize: " << mfSize << " real size calculated from record dataSize: " << dataSize - 16);
     983             : 
     984           0 :                     GraphicFilter filter;
     985             :                     // workaround buggy metafiles, which have wrong mfSize set (n#705956 for example)
     986           0 :                     SvMemoryStream mfStream (((char *)s.GetData()) + s.Tell(), bUseWholeStream ? s.remainingSize() : dataSize - 16, STREAM_READ);
     987             : 
     988           0 :                     filter.ImportGraphic (graphic, OUString(), mfStream);
     989             : 
     990             :                     // debug code - write the stream to debug file /tmp/emf-stream.emf
     991             : #if OSL_DEBUG_LEVEL > 1
     992             :                         mfStream.Seek(0);
     993             :                         static sal_Int32 emfp_debug_stream_number = 0;
     994             :                         OUString emfp_debug_filename = "/tmp/emf-embedded-stream" +
     995             :                             OUString::number(emfp_debug_stream_number++) + ".emf";
     996             : 
     997             :                         SvFileStream file( emfp_debug_filename, STREAM_WRITE | STREAM_TRUNC );
     998             : 
     999             :                         mfStream.WriteStream(file);
    1000             :                         file.Flush();
    1001             :                         file.Close();
    1002             : #endif
    1003             :                 }
    1004           0 :             }
    1005             :         };
    1006             : 
    1007           0 :         struct EMFPFont : public EMFPObject
    1008             :         {
    1009             :             sal_uInt32 version;
    1010             :             float emSize;
    1011             :             sal_uInt32 sizeUnit;
    1012             :             sal_Int32 fontFlags;
    1013             :             OUString family;
    1014             : 
    1015           0 :             void Read (SvMemoryStream &s)
    1016             :             {
    1017             :                 sal_uInt32 header;
    1018             :                 sal_uInt32 reserved;
    1019             :                 sal_uInt32 length;
    1020             : 
    1021           0 :                 s.ReadUInt32( header ).ReadFloat( emSize ).ReadUInt32( sizeUnit ).ReadInt32( fontFlags ).ReadUInt32( reserved ).ReadUInt32( length );
    1022             : 
    1023             :                 OSL_ASSERT( ( header >> 12 ) == 0xdbc01 );
    1024             : 
    1025             :                 SAL_INFO("cppcanvas.emf", "EMF+\tfont\n"
    1026             :                            << "EMF+\theader: 0x" << std::hex << (header >> 12) << " version: 0x" << (header & 0x1fff) << " size: " << std::dec << emSize << " unit: 0x" << std::hex << sizeUnit << std::dec);
    1027             :                 SAL_INFO("cppcanvas.emf", "EMF+\tflags: 0x" << std::hex << fontFlags << " reserved: 0x" << reserved << " length: 0x" << std::hex << length << std::dec);
    1028             : 
    1029           0 :                 if( length > 0 && length < 0x4000 ) {
    1030           0 :                     sal_Unicode *chars = (sal_Unicode *) alloca( sizeof( sal_Unicode ) * length );
    1031             : 
    1032           0 :                     for( sal_uInt32 i = 0; i < length; i++ )
    1033           0 :                         s.ReadUInt16( chars[ i ] );
    1034             : 
    1035           0 :                     family = OUString( chars, length );
    1036             :                     SAL_INFO("cppcanvas.emf", "EMF+\tfamily: " << OUStringToOString( family, RTL_TEXTENCODING_UTF8).getStr()); // TODO: can we just use family?
    1037             :                 }
    1038           0 :             }
    1039             :         };
    1040             : 
    1041           0 :         void ImplRenderer::ReadRectangle (SvStream& s, float& x, float& y, float &width, float& height, bool bCompressed)
    1042             :         {
    1043           0 :             if (bCompressed) {
    1044             :                 sal_Int16 ix, iy, iw, ih;
    1045             : 
    1046           0 :                 s.ReadInt16( ix ).ReadInt16( iy ).ReadInt16( iw ).ReadInt16( ih );
    1047             : 
    1048           0 :                 x = ix;
    1049           0 :                 y = iy;
    1050           0 :                 width = iw;
    1051           0 :                 height = ih;
    1052             :             } else
    1053           0 :                 s.ReadFloat( x ).ReadFloat( y ).ReadFloat( width ).ReadFloat( height );
    1054           0 :         }
    1055             : 
    1056           0 :         void ImplRenderer::ReadPoint (SvStream& s, float& x, float& y, sal_uInt32 flags)
    1057             :         {
    1058           0 :             if (flags & 0x4000) {
    1059             :                 sal_Int16 ix, iy;
    1060             : 
    1061           0 :                 s.ReadInt16( ix ).ReadInt16( iy );
    1062             : 
    1063           0 :                 x = ix;
    1064           0 :                 y = iy;
    1065             :             } else
    1066           0 :                 s.ReadFloat( x ).ReadFloat( y );
    1067           0 :         }
    1068             : 
    1069           0 :         void ImplRenderer::MapToDevice (double& x, double& y)
    1070             :         {
    1071             :             // TODO: other units
    1072           0 :             x = 100*nMmX*x/nPixX;
    1073           0 :             y = 100*nMmY*y/nPixY;
    1074           0 :         }
    1075             : 
    1076           0 :         ::basegfx::B2DPoint ImplRenderer::Map (double ix, double iy)
    1077             :         {
    1078             :             double x, y;
    1079             : 
    1080           0 :             x = ix*aWorldTransform.eM11 + iy*aWorldTransform.eM21 + aWorldTransform.eDx;
    1081           0 :             y = ix*aWorldTransform.eM12 + iy*aWorldTransform.eM22 + aWorldTransform.eDy;
    1082             : 
    1083           0 :             MapToDevice (x, y);
    1084             : 
    1085           0 :             x -= nFrameLeft;
    1086           0 :             y -= nFrameTop;
    1087             : 
    1088           0 :             x *= aBaseTransform.eM11;
    1089           0 :             y *= aBaseTransform.eM22;
    1090             : 
    1091           0 :             return ::basegfx::B2DPoint (x, y);
    1092             :         }
    1093             : 
    1094           0 :         ::basegfx::B2DSize ImplRenderer::MapSize (double iwidth, double iheight)
    1095             :         {
    1096             :             double w, h;
    1097             : 
    1098           0 :             w = iwidth*aWorldTransform.eM11 + iheight*aWorldTransform.eM21;
    1099           0 :             h = iwidth*aWorldTransform.eM12 + iheight*aWorldTransform.eM22;
    1100             : 
    1101           0 :             MapToDevice (w, h);
    1102             : 
    1103           0 :             w *= aBaseTransform.eM11;
    1104           0 :             h *= aBaseTransform.eM22;
    1105             : 
    1106           0 :             return ::basegfx::B2DSize (w, h);
    1107             :         }
    1108             : 
    1109             : #define COLOR(x) \
    1110             :     ::vcl::unotools::colorToDoubleSequence( ::Color (0xff - (x >> 24), \
    1111             :                              (x >> 16) & 0xff, \
    1112             :                              (x >> 8) & 0xff, \
    1113             :                              x & 0xff), \
    1114             :                         rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace());
    1115             : 
    1116           0 :         void ImplRenderer::EMFPPlusFillPolygon (::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms,
    1117             :                                                 OutDevState& rState, const CanvasSharedPtr& rCanvas, bool isColor, sal_uInt32 brushIndexOrColor)
    1118             :         {
    1119           0 :             ::basegfx::B2DPolyPolygon localPolygon (polygon);
    1120             : 
    1121             :             SAL_INFO("cppcanvas.emf", "EMF+\tfill polygon");
    1122             : 
    1123           0 :             localPolygon.transform( rState.mapModeTransform );
    1124             : 
    1125           0 :             ActionSharedPtr pPolyAction;
    1126             : 
    1127           0 :             if (isColor) {
    1128             :                 SAL_INFO("cppcanvas.emf", "EMF+\t\tcolor fill:0x" << std::hex << brushIndexOrColor << std::dec);
    1129           0 :                 rState.isFillColorSet = true;
    1130           0 :                 rState.isLineColorSet = false;
    1131             : 
    1132           0 :                 rState.fillColor = COLOR(brushIndexOrColor);
    1133             : 
    1134           0 :                 pPolyAction = ActionSharedPtr ( internal::PolyPolyActionFactory::createPolyPolyAction( localPolygon, rParms.mrCanvas, rState ) );
    1135             : 
    1136             :             } else {
    1137           0 :                 rState.isFillColorSet = true;
    1138             :                 // extract UseBrush
    1139           0 :                 EMFPBrush* brush = (EMFPBrush*) aObjects [brushIndexOrColor & 0xff];
    1140             :                 SAL_INFO("cppcanvas.emf", "EMF+\tbrush fill slot: " << brushIndexOrColor << " (type: " << brush->GetType () << ")");
    1141             : 
    1142             :                 // give up in case something wrong happened
    1143           0 :                 if( !brush )
    1144           0 :                     return;
    1145             : 
    1146           0 :                 rState.isFillColorSet = false;
    1147           0 :                 rState.isLineColorSet = false;
    1148             : 
    1149           0 :                 if (brush->type == 3 || brush->type == 4) {
    1150             : 
    1151           0 :                     if (brush->type == 3 && !(brush->additionalFlags & 0x1))
    1152           0 :                         return;  // we are unable to parse these brushes yet
    1153             : 
    1154           0 :                     ::basegfx::B2DHomMatrix aTextureTransformation;
    1155           0 :                     ::basegfx::B2DHomMatrix aWorldTransformation;
    1156           0 :                     ::basegfx::B2DHomMatrix aBaseTransformation;
    1157           0 :                     rendering::Texture aTexture;
    1158             : 
    1159           0 :                     aWorldTransformation.set (0, 0, aWorldTransform.eM11);
    1160           0 :                     aWorldTransformation.set (0, 1, aWorldTransform.eM21);
    1161           0 :                     aWorldTransformation.set (0, 2, aWorldTransform.eDx);
    1162           0 :                     aWorldTransformation.set (1, 0, aWorldTransform.eM12);
    1163           0 :                     aWorldTransformation.set (1, 1, aWorldTransform.eM22);
    1164           0 :                     aWorldTransformation.set (1, 2, aWorldTransform.eDy);
    1165             : 
    1166           0 :                     aBaseTransformation.set (0, 0, aBaseTransform.eM11);
    1167           0 :                     aBaseTransformation.set (0, 1, aBaseTransform.eM21);
    1168           0 :                     aBaseTransformation.set (0, 2, aBaseTransform.eDx);
    1169           0 :                     aBaseTransformation.set (1, 0, aBaseTransform.eM12);
    1170           0 :                     aBaseTransformation.set (1, 1, aBaseTransform.eM22);
    1171           0 :                     aBaseTransformation.set (1, 2, aBaseTransform.eDy);
    1172             : 
    1173           0 :                     if (brush->type == 4) {
    1174           0 :                         aTextureTransformation.scale (brush->areaWidth, brush->areaHeight);
    1175           0 :                         aTextureTransformation.translate (brush->areaX, brush->areaY);
    1176             :                     } else {
    1177           0 :                         aTextureTransformation.translate (-0.5, -0.5);
    1178           0 :                         aTextureTransformation.scale (brush->areaWidth, brush->areaHeight);
    1179           0 :                         aTextureTransformation.translate (brush->areaX,brush->areaY);
    1180             :                     }
    1181             : 
    1182           0 :                     if (brush->hasTransformation) {
    1183           0 :                         ::basegfx::B2DHomMatrix aTransformation;
    1184             : 
    1185           0 :                         aTransformation.set (0, 0, brush->transformation.eM11);
    1186           0 :                         aTransformation.set (0, 1, brush->transformation.eM21);
    1187           0 :                         aTransformation.set (0, 2, brush->transformation.eDx);
    1188           0 :                         aTransformation.set (1, 0, brush->transformation.eM12);
    1189           0 :                         aTransformation.set (1, 1, brush->transformation.eM22);
    1190           0 :                         aTransformation.set (1, 2, brush->transformation.eDy);
    1191             : 
    1192           0 :                         aTextureTransformation *= aTransformation;
    1193             :                     }
    1194             : 
    1195           0 :                     aTextureTransformation *= aWorldTransformation;
    1196           0 :                     aTextureTransformation.scale (100.0*nMmX/nPixX, 100.0*nMmY/nPixY);
    1197           0 :                     aTextureTransformation.translate (-nFrameLeft, -nFrameTop);
    1198           0 :                     aTextureTransformation *= rState.mapModeTransform;
    1199           0 :                     aTextureTransformation *= aBaseTransformation;
    1200             : 
    1201           0 :                     aTexture.RepeatModeX = rendering::TexturingMode::CLAMP;
    1202           0 :                     aTexture.RepeatModeY = rendering::TexturingMode::CLAMP;
    1203           0 :                     aTexture.Alpha = 1.0;
    1204             : 
    1205           0 :                     basegfx::ODFGradientInfo aGradInfo;
    1206           0 :                     OUString aGradientService;
    1207             : 
    1208             :                     const uno::Sequence< double > aStartColor(
    1209             :                             ::vcl::unotools::colorToDoubleSequence( brush->solidColor,
    1210           0 :                                 rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() ) );
    1211             :                     const uno::Sequence< double > aEndColor(
    1212             :                             ::vcl::unotools::colorToDoubleSequence( brush->secondColor,
    1213           0 :                                 rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() ) );
    1214           0 :                     uno::Sequence< uno::Sequence < double > > aColors (2);
    1215           0 :                     uno::Sequence< double > aStops (2);
    1216             : 
    1217           0 :                     if (brush->blendPositions) {
    1218             :                         SAL_INFO("cppcanvas.emf", "EMF+\t\tuse blend");
    1219           0 :                         aColors.realloc (brush->blendPoints);
    1220           0 :                         aStops.realloc (brush->blendPoints);
    1221           0 :                         int length = aStartColor.getLength ();
    1222           0 :                         uno::Sequence< double > aColor (length);
    1223             : 
    1224             :                         OSL_ASSERT (length == aEndColor.getLength());
    1225             : 
    1226           0 :                         for (int i = 0; i < brush->blendPoints; i++) {
    1227           0 :                             aStops[i] = brush->blendPositions [i];
    1228             : 
    1229           0 :                             for (int j = 0; j < length; j++) {
    1230           0 :                                 if (brush->type == 4) {
    1231           0 :                                     aColor [j] = aStartColor [j]*(1 - brush->blendFactors[i]) + aEndColor [j]*brush->blendFactors[i];
    1232             :                                 } else
    1233           0 :                                     aColor [j] = aStartColor [j]*brush->blendFactors[i] + aEndColor [j]*(1 - brush->blendFactors[i]);
    1234             :                             }
    1235             : 
    1236           0 :                             aColors[i] = aColor;
    1237           0 :                         }
    1238           0 :                     } else if (brush->colorblendPositions) {
    1239             :                         SAL_INFO("cppcanvas.emf", "EMF+\t\tuse color blend");
    1240           0 :                         aColors.realloc (brush->colorblendPoints);
    1241           0 :                         aStops.realloc (brush->colorblendPoints);
    1242             : 
    1243           0 :                         for (int i = 0; i < brush->colorblendPoints; i++) {
    1244           0 :                             aStops[i] = brush->colorblendPositions [i];
    1245           0 :                             aColors[(brush->type == 4) ? i : brush->colorblendPoints - 1 - i] = ::vcl::unotools::colorToDoubleSequence( brush->colorblendColors [i],
    1246           0 :                                     rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
    1247             :                         }
    1248             :                     } else {
    1249           0 :                         aStops[0] = 0.0;
    1250           0 :                         aStops[1] = 1.0;
    1251             : 
    1252           0 :                         if (brush->type == 4) {
    1253           0 :                             aColors[0] = aStartColor;
    1254           0 :                             aColors[1] = aEndColor;
    1255             :                         } else {
    1256           0 :                             aColors[1] = aStartColor;
    1257           0 :                             aColors[0] = aEndColor;
    1258             :                         }
    1259             :                     }
    1260             : 
    1261             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tset gradient");
    1262           0 :                     basegfx::B2DRange aBoundsRectangle (0, 0, 1, 1);
    1263           0 :                     if (brush->type == 4) {
    1264           0 :                         aGradientService = "LinearGradient";
    1265           0 :                         aGradInfo = basegfx::tools::createLinearODFGradientInfo(
    1266             :                                 aBoundsRectangle,
    1267           0 :                                 aStops.getLength(),
    1268             :                                 0,
    1269           0 :                                 0);
    1270             : 
    1271             :                     } else {
    1272           0 :                         aGradientService = "EllipticalGradient";
    1273           0 :                         aGradInfo = basegfx::tools::createEllipticalODFGradientInfo(
    1274             :                                 aBoundsRectangle,
    1275             :                                 ::basegfx::B2DVector( 0, 0 ),
    1276           0 :                                 aStops.getLength(),
    1277             :                                 0,
    1278           0 :                                 0);
    1279             :                     }
    1280             : 
    1281             :                     uno::Reference< lang::XMultiServiceFactory > xFactory(
    1282           0 :                             rParms.mrCanvas->getUNOCanvas()->getDevice()->getParametricPolyPolygonFactory() );
    1283             : 
    1284           0 :                     if( xFactory.is() ) {
    1285           0 :                         uno::Sequence<uno::Any> args( 3 );
    1286           0 :                         beans::PropertyValue aProp;
    1287           0 :                         aProp.Name = "Colors";
    1288           0 :                         aProp.Value <<= aColors;
    1289           0 :                         args[0] <<= aProp;
    1290           0 :                         aProp.Name = "Stops";
    1291           0 :                         aProp.Value <<= aStops;
    1292           0 :                         args[1] <<= aProp;
    1293           0 :                         aProp.Name = "AspectRatio";
    1294           0 :                         aProp.Value <<= static_cast<sal_Int32>(1);
    1295           0 :                         args[2] <<= aProp;
    1296             : 
    1297             :                         aTexture.Gradient.set(
    1298           0 :                                 xFactory->createInstanceWithArguments( aGradientService,
    1299           0 :                                     args ),
    1300           0 :                                 uno::UNO_QUERY);
    1301             :                     }
    1302             : 
    1303             :                     ::basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform,
    1304           0 :                             aTextureTransformation );
    1305             : 
    1306           0 :                     if( aTexture.Gradient.is() )
    1307           0 :                         pPolyAction =
    1308             :                             ActionSharedPtr ( internal::PolyPolyActionFactory::createPolyPolyAction( localPolygon,
    1309             :                                         rParms.mrCanvas,
    1310             :                                         rState,
    1311           0 :                                         aTexture ) );
    1312             :                 }
    1313             :             }
    1314             : 
    1315           0 :             if( pPolyAction )
    1316             :             {
    1317             :                 SAL_INFO("cppcanvas.emf", "EMF+\t\tadd poly action");
    1318             : 
    1319             :                 maActions.push_back(
    1320             :                     MtfAction(
    1321             :                         pPolyAction,
    1322           0 :                         rParms.mrCurrActionIndex ) );
    1323             : 
    1324           0 :                 rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
    1325           0 :             }
    1326             :         }
    1327             : 
    1328           0 :         double ImplRenderer::EMFPPlusDrawLineCap(const ::basegfx::B2DPolygon& rPolygon, double fPolyLength,
    1329             :                 const ::basegfx::B2DPolyPolygon& rLineCap, bool bIsFilled, bool bStart, const rendering::StrokeAttributes& rAttributes,
    1330             :                 const ActionFactoryParameters& rParms, OutDevState& rState)
    1331             :         {
    1332           0 :             if (!rLineCap.count())
    1333           0 :                 return 0.0;
    1334             : 
    1335             :             // createAreaGeometryForLineStartEnd normalises the arrows height
    1336             :             // before scaling (i.e. scales down by rPolygon.height), hence
    1337             :             // we pre-scale it (which means we can avoid changing the logic
    1338             :             // that would affect arrows rendered outside of EMF+).
    1339           0 :             const double fWidth = rAttributes.StrokeWidth*rLineCap.getB2DRange().getWidth();
    1340             : 
    1341             :             // When drawing an outline (as opposed to a filled endCap), we also
    1342             :             // need to take account that the brush width also adds to the area
    1343             :             // of the polygon.
    1344           0 :             const double fShift = bIsFilled ? 0 : rAttributes.StrokeWidth;
    1345           0 :             double fConsumed = 0;
    1346             :             basegfx::B2DPolyPolygon aArrow(basegfx::tools::createAreaGeometryForLineStartEnd(
    1347             :                         rPolygon, rLineCap, bStart,
    1348           0 :                         fWidth, fPolyLength, 0, &fConsumed, fShift));
    1349             : 
    1350             :             // createAreaGeometryForLineStartEnd from some reason always sets
    1351             :             // the path as closed, correct it
    1352           0 :             aArrow.setClosed(rLineCap.isClosed());
    1353             : 
    1354             :             // If the endcap is filled, we draw ONLY the filling, if it isn't
    1355             :             // filled we draw ONLY the outline, but never both.
    1356           0 :             if (bIsFilled)
    1357             :             {
    1358           0 :                 bool bWasFillColorSet = rState.isFillColorSet;
    1359           0 :                 rState.isFillColorSet = true;
    1360           0 :                 rState.fillColor = rState.lineColor;
    1361           0 :                 ActionSharedPtr pAction2(internal::PolyPolyActionFactory::createPolyPolyAction(aArrow, rParms.mrCanvas, rState));
    1362           0 :                 if (pAction2)
    1363             :                 {
    1364           0 :                     maActions.push_back(MtfAction(pAction2, rParms.mrCurrActionIndex));
    1365           0 :                     rParms.mrCurrActionIndex += pAction2->getActionCount()-1;
    1366             :                 }
    1367           0 :                 rState.isFillColorSet = bWasFillColorSet;
    1368             :             }
    1369             :             else
    1370             :             {
    1371           0 :                 ActionSharedPtr pAction(internal::PolyPolyActionFactory::createPolyPolyAction(aArrow, rParms.mrCanvas, rState, rAttributes));
    1372           0 :                 if (pAction)
    1373             :                 {
    1374           0 :                     maActions.push_back(MtfAction(pAction, rParms.mrCurrActionIndex));
    1375           0 :                     rParms.mrCurrActionIndex += pAction->getActionCount()-1;
    1376           0 :                 }
    1377             :             }
    1378             : 
    1379             :             // There isn't any clear definition of how far the line should extend
    1380             :             // for arrows, however the following values seem to give best results
    1381             :             // (fConsumed/2 draws the line to the center-point of the endcap
    1382             :             // for filled caps -- however it is likely this will need to be
    1383             :             // changed once we start taking baseInset into account).
    1384           0 :             if (bIsFilled)
    1385           0 :                 return fConsumed/2;
    1386             :             else
    1387           0 :                 return rAttributes.StrokeWidth;
    1388             :         }
    1389             : 
    1390           0 :         void ImplRenderer::EMFPPlusDrawPolygon (const ::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms,
    1391             :                                                 OutDevState& rState, const CanvasSharedPtr& rCanvas, sal_uInt32 penIndex)
    1392             :         {
    1393           0 :             EMFPPen* pen = (EMFPPen*) aObjects [penIndex & 0xff];
    1394             : 
    1395             :             SAL_WARN_IF( !pen, "cppcanvas.emf", "emf+ missing pen" );
    1396             : 
    1397           0 :             if (pen)
    1398             :             {
    1399           0 :                 rState.isFillColorSet = false;
    1400           0 :                 rState.isLineColorSet = true;
    1401           0 :                 rState.lineColor = ::vcl::unotools::colorToDoubleSequence (pen->GetColor (),
    1402           0 :                                                                            rCanvas->getUNOCanvas ()->getDevice()->getDeviceColorSpace());
    1403             : 
    1404           0 :                 basegfx::B2DPolyPolygon aPolyPolygon(polygon);
    1405           0 :                 aPolyPolygon.transform(rState.mapModeTransform);
    1406           0 :                 rendering::StrokeAttributes aCommonAttributes;
    1407             : 
    1408             :                 // some attributes are common for the polygon, and the line
    1409             :                 // starts & ends - like the stroke width
    1410           0 :                 pen->SetStrokeWidth(aCommonAttributes, *this, rState);
    1411             : 
    1412             :                 // but eg. dashing has to be additionally set only on the
    1413             :                 // polygon
    1414           0 :                 rendering::StrokeAttributes aPolygonAttributes(aCommonAttributes);
    1415           0 :                 pen->SetStrokeAttributes(aPolygonAttributes);
    1416             : 
    1417           0 :                 basegfx::B2DPolyPolygon aFinalPolyPolygon;
    1418             : 
    1419             :                 // render line starts & ends if present
    1420           0 :                 if (!pen->customStartCap && !pen->customEndCap)
    1421           0 :                     aFinalPolyPolygon = aPolyPolygon;
    1422             :                 else
    1423             :                 {
    1424           0 :                     for (sal_uInt32 i = 0; i < aPolyPolygon.count(); ++i)
    1425             :                     {
    1426           0 :                         basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(i));
    1427             : 
    1428           0 :                         if (!aPolygon.isClosed())
    1429             :                         {
    1430           0 :                             double fStart = 0.0;
    1431           0 :                             double fEnd = 0.0;
    1432           0 :                             double fPolyLength = basegfx::tools::getLength(aPolygon);
    1433             : 
    1434             :                             // line start
    1435           0 :                             if (pen->customStartCap)
    1436             :                             {
    1437           0 :                                 rendering::StrokeAttributes aAttributes(aCommonAttributes);
    1438           0 :                                 pen->customStartCap->SetAttributes(aAttributes);
    1439             : 
    1440             :                                 fStart = EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customStartCap->polygon,
    1441             :                                         pen->customStartCap->mbIsFilled,
    1442           0 :                                         true, aAttributes, rParms, rState);
    1443             :                             }
    1444             : 
    1445             :                             // line end
    1446           0 :                             if (pen->customEndCap)
    1447             :                             {
    1448           0 :                                 rendering::StrokeAttributes aAttributes(aCommonAttributes);
    1449           0 :                                 pen->customEndCap->SetAttributes(aAttributes);
    1450             : 
    1451             :                                 fEnd = EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customEndCap->polygon,
    1452             :                                         pen->customEndCap->mbIsFilled,
    1453           0 :                                         false, aAttributes, rParms, rState);
    1454             :                             }
    1455             : 
    1456             :                             // build new poly, consume something from the old poly
    1457           0 :                             if (fStart != 0.0 || fEnd != 0.0)
    1458           0 :                                 aPolygon = basegfx::tools::getSnippetAbsolute(aPolygon, fStart, fPolyLength - fEnd, fPolyLength);
    1459             :                         }
    1460             : 
    1461           0 :                         aFinalPolyPolygon.append(aPolygon);
    1462           0 :                     }
    1463             :                 }
    1464             : 
    1465             :                 // finally render the polygon
    1466           0 :                 ActionSharedPtr pPolyAction(internal::PolyPolyActionFactory::createPolyPolyAction(aFinalPolyPolygon, rParms.mrCanvas, rState, aPolygonAttributes));
    1467           0 :                 if( pPolyAction )
    1468             :                 {
    1469           0 :                     maActions.push_back(MtfAction(pPolyAction, rParms.mrCurrActionIndex));
    1470           0 :                     rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
    1471           0 :                 }
    1472             :             }
    1473           0 :         }
    1474             : 
    1475           0 :         void ImplRenderer::processObjectRecord(SvMemoryStream& rObjectStream, sal_uInt16 flags, sal_uInt32 dataSize, bool bUseWholeStream)
    1476             :         {
    1477             :             sal_uInt32 index;
    1478             : 
    1479             :             SAL_INFO("cppcanvas.emf", "EMF+ Object slot: " << (flags & 0xff) << " flags: " << (flags & 0xff00));
    1480             : 
    1481           0 :             index = flags & 0xff;
    1482           0 :             if (aObjects [index] != NULL) {
    1483           0 :                 delete aObjects [index];
    1484           0 :                 aObjects [index] = NULL;
    1485             :             }
    1486             : 
    1487           0 :             switch (flags & 0x7f00) {
    1488             :             case EmfPlusObjectTypeBrush:
    1489             :                 {
    1490             :                     EMFPBrush *brush;
    1491           0 :                     aObjects [index] = brush = new EMFPBrush ();
    1492           0 :                     brush->Read (rObjectStream, *this);
    1493             : 
    1494           0 :                     break;
    1495             :                 }
    1496             :             case EmfPlusObjectTypePen:
    1497             :                 {
    1498             :                     EMFPPen *pen;
    1499           0 :                     aObjects [index] = pen = new EMFPPen ();
    1500           0 :                     pen->Read (rObjectStream, *this, nHDPI, nVDPI);
    1501             : 
    1502           0 :                     break;
    1503             :                 }
    1504             :             case EmfPlusObjectTypePath:
    1505             :                 sal_uInt32 header, pathFlags;
    1506             :                 sal_Int32 points;
    1507             : 
    1508           0 :                 rObjectStream.ReadUInt32( header ).ReadInt32( points ).ReadUInt32( pathFlags );
    1509             : 
    1510             :                 SAL_INFO("cppcanvas.emf", "EMF+\tpath");
    1511             :                 SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " points: " << std::dec << points << " additional flags: 0x" << std::hex << pathFlags << std::dec);
    1512             : 
    1513             :                 EMFPPath *path;
    1514           0 :                 aObjects [index] = path = new EMFPPath (points);
    1515           0 :                 path->Read (rObjectStream, pathFlags, *this);
    1516             : 
    1517           0 :                 break;
    1518             :             case EmfPlusObjectTypeRegion: {
    1519             :                 EMFPRegion *region;
    1520             : 
    1521           0 :                 aObjects [index] = region = new EMFPRegion ();
    1522           0 :                 region->Read (rObjectStream);
    1523             : 
    1524           0 :                 break;
    1525             :             }
    1526             :             case EmfPlusObjectTypeImage:
    1527             :                 {
    1528             :                     EMFPImage *image;
    1529           0 :                     aObjects [index] = image = new EMFPImage ();
    1530           0 :                     image->Read (rObjectStream, dataSize, bUseWholeStream);
    1531             : 
    1532           0 :                     break;
    1533             :                 }
    1534             :             case EmfPlusObjectTypeFont:
    1535             :                 {
    1536             :                     EMFPFont *font;
    1537           0 :                     aObjects [index] = font = new EMFPFont ();
    1538           0 :                     font->Read (rObjectStream);
    1539             : 
    1540           0 :                     break;
    1541             :                 }
    1542             :             default:
    1543             :                 SAL_INFO("cppcanvas.emf", "EMF+\tObject unhandled flags: 0x" << std::hex << (flags & 0xff00) << std::dec);
    1544           0 :                 break;
    1545             :             }
    1546           0 :         }
    1547             : 
    1548           0 :         double ImplRenderer::setFont (sal_uInt8 objectId, const ActionFactoryParameters& rParms, OutDevState& rState)
    1549             :         {
    1550           0 :             EMFPFont *font = (EMFPFont*) aObjects[ objectId ];
    1551             : 
    1552           0 :             rendering::FontRequest aFontRequest;
    1553           0 :             aFontRequest.FontDescription.FamilyName = font->family;
    1554           0 :             double cellSize = font->emSize;
    1555           0 :             aFontRequest.CellSize = (rState.mapModeTransform*MapSize( cellSize, 0 )).getX();
    1556           0 :             rState.xFont = rParms.mrCanvas->getUNOCanvas()->createFont( aFontRequest,
    1557             :                                                uno::Sequence< beans::PropertyValue >(),
    1558           0 :                                                geometry::Matrix2D() );
    1559             : 
    1560           0 :             return cellSize;
    1561             :         }
    1562             : 
    1563           0 :         void ImplRenderer::GraphicStatePush(GraphicStateMap& map, sal_Int32 index, OutDevState& rState)
    1564             :         {
    1565           0 :             GraphicStateMap::iterator iter = map.find( index );
    1566             : 
    1567           0 :             if ( iter != map.end() )
    1568             :             {
    1569           0 :                 EmfPlusGraphicState state = iter->second;
    1570           0 :                 map.erase( iter );
    1571             : 
    1572           0 :                 SAL_INFO("cppcanvas.emf", "stack index: " << index << " found and erased");
    1573             :             }
    1574             : 
    1575           0 :             EmfPlusGraphicState state;
    1576             : 
    1577           0 :             state.aWorldTransform = aWorldTransform;
    1578           0 :             state.aDevState = rState;
    1579             : 
    1580           0 :             map[ index ] = state;
    1581           0 :         }
    1582             : 
    1583           0 :         void ImplRenderer::GraphicStatePop(GraphicStateMap& map, sal_Int32 index, OutDevState& rState)
    1584             :         {
    1585           0 :             GraphicStateMap::iterator iter = map.find( index );
    1586             : 
    1587           0 :             if ( iter != map.end() )
    1588             :             {
    1589             :                 SAL_INFO("cppcanvas.emf", "stack index: " << index << " found");
    1590             : 
    1591           0 :                 EmfPlusGraphicState state = iter->second;
    1592             : 
    1593           0 :                 aWorldTransform = state.aWorldTransform;
    1594           0 :                 rState.clip = state.aDevState.clip;
    1595           0 :                 rState.clipRect = state.aDevState.clipRect;
    1596           0 :                 rState.xClipPoly = state.aDevState.xClipPoly;
    1597             :             }
    1598           0 :         }
    1599             : 
    1600           0 :         void ImplRenderer::processEMFPlus( MetaCommentAction* pAct, const ActionFactoryParameters& rFactoryParms,
    1601             :                                            OutDevState& rState, const CanvasSharedPtr& rCanvas )
    1602             :         {
    1603           0 :             sal_uInt32 length = pAct->GetDataSize ();
    1604           0 :             SvMemoryStream rMF ((void*) pAct->GetData (), length, STREAM_READ);
    1605             : 
    1606           0 :             length -= 4;
    1607             : 
    1608           0 :             while (length > 0) {
    1609             :                 sal_uInt16 type, flags;
    1610             :                 sal_uInt32 size, dataSize;
    1611             :                 sal_Size next;
    1612             : 
    1613           0 :                 rMF.ReadUInt16( type ).ReadUInt16( flags ).ReadUInt32( size ).ReadUInt32( dataSize );
    1614             : 
    1615           0 :                 next = rMF.Tell() + ( size - 12 );
    1616             : 
    1617           0 :                 if (size < 12) {
    1618             :                     SAL_INFO("cppcanvas.emf", "Size field is less than 12 bytes");
    1619             :                 }
    1620             : 
    1621             :                 SAL_INFO("cppcanvas.emf", "EMF+ record size: " << size << " type: " << type << " flags: " << flags << " data size: " << dataSize);
    1622             : 
    1623           0 :                 if (type == EmfPlusRecordTypeObject && ((mbMultipart && (flags & 0x7fff) == (mMFlags & 0x7fff)) || (flags & 0x8000))) {
    1624           0 :                     if (!mbMultipart) {
    1625           0 :                         mbMultipart = true;
    1626           0 :                         mMFlags = flags;
    1627           0 :                         mMStream.Seek(0);
    1628             :                     }
    1629             : 
    1630             :                     // 1st 4 bytes are unknown
    1631           0 :                     mMStream.Write (((const char *)rMF.GetData()) + rMF.Tell() + 4, dataSize - 4);
    1632           0 :                     SAL_INFO("cppcanvas.emf", "EMF+ read next object part size: " << size << " type: " << type << " flags: " << flags << " data size: " << dataSize);
    1633             :                 } else {
    1634           0 :                     if (mbMultipart) {
    1635             :                         SAL_INFO("cppcanvas.emf", "EMF+ multipart record flags: " << mMFlags);
    1636           0 :                         mMStream.Seek (0);
    1637           0 :                         processObjectRecord (mMStream, mMFlags, dataSize, true);
    1638             :                     }
    1639           0 :                     mbMultipart = false;
    1640             :                 }
    1641             : 
    1642           0 :                 if (type != EmfPlusRecordTypeObject || !(flags & 0x8000))
    1643             :                 {
    1644           0 :                     switch (type) {
    1645             :                     case EmfPlusRecordTypeHeader:
    1646             :                         sal_uInt32 header, version;
    1647             : 
    1648           0 :                         rMF.ReadUInt32( header ).ReadUInt32( version ).ReadInt32( nHDPI ).ReadInt32( nVDPI );
    1649             : 
    1650             :                         SAL_INFO("cppcanvas.emf", "EMF+ Header");
    1651             :                         SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " version: " << std::dec << version << " horizontal DPI: " << nHDPI << " vertical DPI: " << nVDPI << " dual: " << (flags & 1));
    1652             : 
    1653           0 :                         break;
    1654             :                     case EmfPlusRecordTypeEndOfFile:
    1655             :                         SAL_INFO("cppcanvas.emf", "EMF+ EndOfFile");
    1656           0 :                         break;
    1657             :                     case EmfPlusRecordTypeGetDC:
    1658             :                         SAL_INFO("cppcanvas.emf", "EMF+ GetDC");
    1659             :                         SAL_INFO("cppcanvas.emf", "EMF+\talready used in svtools wmf/emf filter parser");
    1660           0 :                         break;
    1661             :                     case EmfPlusRecordTypeObject:
    1662           0 :                         processObjectRecord (rMF, flags, dataSize);
    1663           0 :                         break;
    1664             :                     case EmfPlusRecordTypeFillPie:
    1665             :                         {
    1666             :                             sal_uInt32 brushIndexOrColor;
    1667             :                             float startAngle, sweepAngle;
    1668             : 
    1669           0 :                             rMF.ReadUInt32( brushIndexOrColor ).ReadFloat( startAngle ).ReadFloat( sweepAngle );
    1670             : 
    1671             :                             SAL_INFO("cppcanvas.emf", "EMF+ FillPie colorOrIndex: " << brushIndexOrColor << " startAngle: " << startAngle << " sweepAngle: " << sweepAngle);
    1672             : 
    1673             :                             float dx, dy, dw, dh;
    1674             : 
    1675           0 :                             ReadRectangle (rMF, dx, dy, dw, dh, flags & 0x4000);
    1676             : 
    1677             :                             SAL_INFO("cppcanvas.emf", "EMF+ RectData: " << dx << "," << dy << " " << dw << "x" << dh);
    1678             : 
    1679           0 :                             startAngle = 2*M_PI*startAngle/360;
    1680           0 :                             sweepAngle = 2*M_PI*sweepAngle/360;
    1681             : 
    1682           0 :                             B2DPoint mappedCenter (Map (dx + dw/2, dy + dh/2));
    1683           0 :                             B2DSize mappedSize( MapSize (dw/2, dh/2));
    1684             : 
    1685           0 :                             float endAngle = startAngle + sweepAngle;
    1686           0 :                             startAngle = fmodf(startAngle, static_cast<float>(M_PI*2));
    1687           0 :                             if (startAngle < 0)
    1688           0 :                                 startAngle += static_cast<float>(M_PI*2);
    1689           0 :                             endAngle = fmodf(endAngle, static_cast<float>(M_PI*2));
    1690           0 :                             if (endAngle < 0)
    1691           0 :                                 endAngle += static_cast<float>(M_PI*2);
    1692             : 
    1693           0 :                             if (sweepAngle < 0)
    1694           0 :                                 std::swap (endAngle, startAngle);
    1695             : 
    1696             :                             SAL_INFO("cppcanvas.emf", "EMF+ adjusted angles: start " <<
    1697             :                                      (360.0*startAngle/M_PI) << ", end: " << (360.0*endAngle/M_PI));
    1698             : 
    1699           0 :                             B2DPolygon polygon = basegfx::tools::createPolygonFromEllipseSegment (mappedCenter, mappedSize.getX (), mappedSize.getY (), startAngle, endAngle);
    1700           0 :                             polygon.append (mappedCenter);
    1701           0 :                             polygon.setClosed (true);
    1702             : 
    1703           0 :                             B2DPolyPolygon polyPolygon (polygon);
    1704           0 :                             EMFPPlusFillPolygon (polyPolygon, rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
    1705             :                         }
    1706           0 :                         break;
    1707             :                     case EmfPlusRecordTypeFillPath:
    1708             :                         {
    1709           0 :                             sal_uInt32 index = flags & 0xff;
    1710             :                             sal_uInt32 brushIndexOrColor;
    1711             : 
    1712           0 :                             rMF.ReadUInt32( brushIndexOrColor );
    1713             : 
    1714             :                             SAL_INFO("cppcanvas.emf", "EMF+ FillPath slot: " << index);
    1715             : 
    1716           0 :                             EMFPPlusFillPolygon (((EMFPPath*) aObjects [index])->GetPolygon (*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
    1717             :                         }
    1718           0 :                         break;
    1719             :                     case EmfPlusRecordTypeDrawEllipse:
    1720             :                     case EmfPlusRecordTypeFillEllipse:
    1721             :                         {
    1722             :                             // Intentionally very bogus initial value to avoid MSVC complaining about potentially uninitialized local
    1723             :                             // variable. As long as the code stays as intended, this variable will be assigned a (real) value in the case
    1724             :                             // when it is later used.
    1725           0 :                             sal_uInt32 brushIndexOrColor = 1234567;
    1726             : 
    1727           0 :                             if ( type == EmfPlusRecordTypeFillEllipse )
    1728           0 :                                 rMF.ReadUInt32( brushIndexOrColor );
    1729             : 
    1730             :                             SAL_INFO("cppcanvas.emf", "EMF+ " << (type == EmfPlusRecordTypeFillEllipse ? "Fill" : "Draw") << "Ellipse slot: " << (flags & 0xff));
    1731             : 
    1732             :                             float dx, dy, dw, dh;
    1733             : 
    1734           0 :                             ReadRectangle (rMF, dx, dy, dw, dh, flags & 0x4000);
    1735             : 
    1736             :                             SAL_INFO("cppcanvas.emf", "EMF+ RectData: " << dx << "," << dy << " " << dw << "x" << dh);
    1737             : 
    1738           0 :                             B2DPoint mappedCenter (Map (dx + dw/2, dy + dh/2));
    1739           0 :                             B2DSize mappedSize( MapSize (dw/2, dh/2));
    1740             : 
    1741           0 :                             ::basegfx::B2DPolyPolygon polyPolygon( ::basegfx::B2DPolygon( ::basegfx::tools::createPolygonFromEllipse( mappedCenter, mappedSize.getX (), mappedSize.getY () ) ) );
    1742             : 
    1743           0 :                             if ( type == EmfPlusRecordTypeFillEllipse )
    1744             :                                 EMFPPlusFillPolygon( polyPolygon,
    1745           0 :                                                      rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor );
    1746             :                             else
    1747             :                                 EMFPPlusDrawPolygon( polyPolygon,
    1748           0 :                                                      rFactoryParms, rState, rCanvas, flags & 0xff );
    1749             :                         }
    1750           0 :                         break;
    1751             :                     case EmfPlusRecordTypeFillRects:
    1752             :                         {
    1753             :                             SAL_INFO("cppcanvas.emf", "EMF+ FillRects");
    1754             : 
    1755             :                             sal_uInt32 brushIndexOrColor;
    1756             :                             sal_Int32 rectangles;
    1757           0 :                             bool isColor = (flags & 0x8000);
    1758           0 :                             ::basegfx::B2DPolygon polygon;
    1759             : 
    1760           0 :                             rMF.ReadUInt32( brushIndexOrColor ).ReadInt32( rectangles );
    1761             : 
    1762             :                             SAL_INFO("cppcanvas.emf", "EMF+\t" << ((flags & 0x8000) ? "color" : "brush index") << ": 0x" << std::hex << brushIndexOrColor << std::dec);
    1763             : 
    1764           0 :                             for (int i=0; i < rectangles; i++) {
    1765           0 :                                 if (flags & 0x4000) {
    1766             :                                     /* 16bit integers */
    1767             :                                     sal_Int16 x, y, width, height;
    1768             : 
    1769           0 :                                     rMF.ReadInt16( x ).ReadInt16( y ).ReadInt16( width ).ReadInt16( height );
    1770             : 
    1771           0 :                                     polygon.append (Map (x, y));
    1772           0 :                                     polygon.append (Map (x + width, y));
    1773           0 :                                     polygon.append (Map (x + width, y + height));
    1774           0 :                                     polygon.append (Map (x, y + height));
    1775             : 
    1776             :                                     SAL_INFO("cppcanvas.emf", "EMF+\trectangle: " << x << "," << " " << width << "x" << height);
    1777             :                                 } else {
    1778             :                                     /* Single's */
    1779             :                                     float x, y, width, height;
    1780             : 
    1781           0 :                                     rMF.ReadFloat( x ).ReadFloat( y ).ReadFloat( width ).ReadFloat( height );
    1782             : 
    1783           0 :                                     polygon.append (Map (x, y));
    1784           0 :                                     polygon.append (Map (x + width, y));
    1785           0 :                                     polygon.append (Map (x + width, y + height));
    1786           0 :                                     polygon.append (Map (x, y + height));
    1787             : 
    1788             :                                     SAL_INFO("cppcanvas.emf", "EMF+\trectangle: " << x << "," << " " << width << "x" << height);
    1789             :                                 }
    1790             : 
    1791           0 :                                 ::basegfx::B2DPolyPolygon polyPolygon (polygon);
    1792             : 
    1793           0 :                                 EMFPPlusFillPolygon (polyPolygon, rFactoryParms, rState, rCanvas, isColor, brushIndexOrColor);
    1794           0 :                             }
    1795           0 :                             break;
    1796             :                         }
    1797             :                     case EmfPlusRecordTypeFillPolygon:
    1798             :                         {
    1799           0 :                             sal_uInt8 index = flags & 0xff;
    1800             :                             sal_uInt32 brushIndexOrColor;
    1801             :                             sal_Int32 points;
    1802             : 
    1803           0 :                             rMF.ReadUInt32( brushIndexOrColor );
    1804           0 :                             rMF.ReadInt32( points );
    1805             : 
    1806             :                             SAL_INFO("cppcanvas.emf", "EMF+ FillPolygon in slot: " << +index << " points: " << points);
    1807             :                             SAL_INFO("cppcanvas.emf", "EMF+\t: " << ((flags & 0x8000) ? "color" : "brush index") << " 0x" << std::hex << brushIndexOrColor << std::dec);
    1808             : 
    1809           0 :                             EMFPPath path (points, true);
    1810           0 :                             path.Read (rMF, flags, *this);
    1811             : 
    1812           0 :                             EMFPPlusFillPolygon (path.GetPolygon (*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
    1813             : 
    1814           0 :                             break;
    1815             :                         }
    1816             :                     case EmfPlusRecordTypeDrawLines:
    1817             :                         {
    1818             :                             sal_uInt32 points;
    1819             : 
    1820           0 :                             rMF.ReadUInt32( points );
    1821             : 
    1822             :                             SAL_INFO("cppcanvas.emf", "EMF+ DrawLines in slot: " << (flags & 0xff) << " points: " << points);
    1823             : 
    1824           0 :                             EMFPPath path (points, true);
    1825           0 :                             path.Read (rMF, flags, *this);
    1826             : 
    1827           0 :                             EMFPPlusDrawPolygon (path.GetPolygon (*this), rFactoryParms, rState, rCanvas, flags);
    1828             : 
    1829           0 :                             break;
    1830             :                         }
    1831             :                     case EmfPlusRecordTypeDrawPath:
    1832             :                         {
    1833             :                             sal_uInt32 penIndex;
    1834             : 
    1835           0 :                             rMF.ReadUInt32( penIndex );
    1836             : 
    1837             :                             SAL_INFO("cppcanvas.emf", "EMF+ DrawPath");
    1838             :                             SAL_INFO("cppcanvas.emf", "EMF+\tpen: " << penIndex);
    1839             : 
    1840           0 :                             EMFPPath* path = (EMFPPath*) aObjects [flags & 0xff];
    1841             :                             SAL_WARN_IF( !path, "cppcanvas.emf", "EmfPlusRecordTypeDrawPath missing path" );
    1842             : 
    1843           0 :                             EMFPPlusDrawPolygon (path->GetPolygon (*this), rFactoryParms, rState, rCanvas, penIndex);
    1844             : 
    1845           0 :                             break;
    1846             :                         }
    1847             :                     case EmfPlusRecordTypeDrawImage:
    1848             :                     case EmfPlusRecordTypeDrawImagePoints:
    1849             :                         {
    1850             :                             sal_uInt32 attrIndex;
    1851             :                             sal_Int32 sourceUnit;
    1852             : 
    1853           0 :                             rMF.ReadUInt32( attrIndex ).ReadInt32( sourceUnit );
    1854             : 
    1855             :                             SAL_INFO("cppcanvas.emf", "EMF+ " << (type == EmfPlusRecordTypeDrawImagePoints ? "DrawImagePoints" : "DrawImage") << "attributes index: " << attrIndex << "source unit: " << sourceUnit);
    1856             :                             SAL_INFO("cppcanvas.emf", "EMF+\tTODO: use image attributes");
    1857             : 
    1858           0 :                             if (sourceUnit == 2 && aObjects [flags & 0xff]) { // we handle only GraphicsUnit.Pixel now
    1859           0 :                                 EMFPImage& image = *(EMFPImage *) aObjects [flags & 0xff];
    1860             :                                 float sx, sy, sw, sh;
    1861             :                                 sal_Int32 aCount;
    1862             : 
    1863           0 :                                 ReadRectangle (rMF, sx, sy, sw, sh);
    1864           0 :                                 Rectangle aSource(Point(sx, sy), Size(sw, sh));
    1865             : 
    1866             :                                 SAL_INFO("cppcanvas.emf", "EMF+ " << (type == EmfPlusRecordTypeDrawImagePoints ? "DrawImagePoints" : "DrawImage") << " source rectangle: " << sx << "," << sy << " " << sw << "x" << sh);
    1867             : 
    1868           0 :                                 ::basegfx::B2DPoint aDstPoint;
    1869           0 :                                 ::basegfx::B2DSize aDstSize;
    1870           0 :                                 bool bValid = false;
    1871             : 
    1872           0 :                                 if (type == EmfPlusRecordTypeDrawImagePoints) {
    1873           0 :                                     rMF.ReadInt32( aCount );
    1874             : 
    1875           0 :                                     if( aCount == 3) { // TODO: now that we now that this value is count we should support it better
    1876             :                                         float x1, y1, x2, y2, x3, y3;
    1877             : 
    1878           0 :                                         ReadPoint (rMF, x1, y1, flags);
    1879           0 :                                         ReadPoint (rMF, x2, y2, flags);
    1880           0 :                                         ReadPoint (rMF, x3, y3, flags);
    1881             : 
    1882             :                                         SAL_INFO("cppcanvas.emf", "EMF+ destination points: " << x1 << "," << y1 << " " << x2 << "," << y2 << " " << x3 << "," << y3);
    1883             :                                         SAL_INFO("cppcanvas.emf", "EMF+ destination rectangle: " << x1 << "," << y1 << " " << x2 - x1 << "x" << y3 - y1);
    1884             : 
    1885           0 :                                         aDstPoint = Map (x1, y1);
    1886           0 :                                         aDstSize = MapSize(x2 - x1, y3 - y1);
    1887             : 
    1888           0 :                                         bValid = true;
    1889             :                                     }
    1890           0 :                                 } else if (type == EmfPlusRecordTypeDrawImage) {
    1891             :                                     float dx, dy, dw, dh;
    1892             : 
    1893           0 :                                     ReadRectangle (rMF, dx, dy, dw, dh, flags & 0x4000);
    1894             : 
    1895             :                                     SAL_INFO("cppcanvas.emf", "EMF+ destination rectangle: " << dx << "," << dy << " " << dw << "x" << dh);
    1896             : 
    1897           0 :                                     aDstPoint = Map (dx, dy);
    1898           0 :                                     aDstSize = MapSize(dw, dh);
    1899             : 
    1900           0 :                                     bValid = true;
    1901             :                                 }
    1902             : 
    1903           0 :                                 if (bValid) {
    1904           0 :                                     BitmapEx aBmp( image.graphic.GetBitmapEx () );
    1905           0 :                                     aBmp.Crop( aSource );
    1906             : 
    1907           0 :                                     Size aSize( aBmp.GetSizePixel() );
    1908             :                                     SAL_INFO("cppcanvas.emf", "EMF+ bitmap size: " << aSize.Width() << "x" << aSize.Height());
    1909           0 :                                     if( aSize.Width() > 0 && aSize.Height() > 0 ) {
    1910             :                                         ActionSharedPtr pBmpAction (
    1911             :                                             internal::BitmapActionFactory::createBitmapAction (
    1912             :                                                 aBmp,
    1913           0 :                                                 rState.mapModeTransform * aDstPoint,
    1914           0 :                                                 rState.mapModeTransform * aDstSize,
    1915             :                                                 rCanvas,
    1916           0 :                                                 rState));
    1917             : 
    1918           0 :                                         if( pBmpAction ) {
    1919             :                                             maActions.push_back( MtfAction( pBmpAction,
    1920           0 :                                                                             rFactoryParms.mrCurrActionIndex ) );
    1921             : 
    1922           0 :                                             rFactoryParms.mrCurrActionIndex += pBmpAction->getActionCount()-1;
    1923           0 :                                         }
    1924             :                                     } else {
    1925             :                                         SAL_INFO("cppcanvas.emf", "EMF+ warning: empty bitmap");
    1926           0 :                                     }
    1927             :                                 } else {
    1928             :                                     SAL_INFO("cppcanvas.emf", "EMF+ DrawImage(Points) TODO (fixme)");
    1929           0 :                                 }
    1930             :                             } else {
    1931             :                                 SAL_INFO("cppcanvas.emf", "EMF+ DrawImage(Points) TODO (fixme) - possibly unsupported source units for crop rectangle");
    1932             :                             }
    1933           0 :                             break;
    1934             :                         }
    1935             :                     case EmfPlusRecordTypeDrawString:
    1936             :                         {
    1937             :                             SAL_INFO("cppcanvas.emf", "EMF+ DrawString");
    1938             : 
    1939             :                             sal_uInt32 brushId;
    1940             :                             sal_uInt32 formatId;
    1941             :                             sal_uInt32 stringLength;
    1942             : 
    1943           0 :                             rMF.ReadUInt32( brushId ).ReadUInt32( formatId ).ReadUInt32( stringLength );
    1944             :                             SAL_INFO("cppcanvas.emf", "EMF+ DrawString brushId: " << brushId << " formatId: " << formatId << " length: " << stringLength);
    1945             : 
    1946           0 :                             if (flags & 0x8000) {
    1947             :                                 float lx, ly, lw, lh;
    1948             : 
    1949           0 :                                 rMF.ReadFloat( lx ).ReadFloat( ly ).ReadFloat( lw ).ReadFloat( lh );
    1950             : 
    1951             :                                 SAL_INFO("cppcanvas.emf", "EMF+ DrawString layoutRect: " << lx << "," << ly << " - " << lw << "x" << lh);
    1952             : 
    1953           0 :                                 OUString text = read_uInt16s_ToOUString(rMF, stringLength);
    1954             : 
    1955           0 :                                 double cellSize = setFont (flags & 0xff, rFactoryParms, rState);
    1956           0 :                                 rState.textColor = COLOR( brushId );
    1957             : 
    1958           0 :                                 ::basegfx::B2DPoint point( Map( lx + 0.15*cellSize, ly + cellSize ) );
    1959             : 
    1960             :                                 ActionSharedPtr pTextAction(
    1961             :                                     TextActionFactory::createTextAction(
    1962             :                                                                         // position is just rough guess for now
    1963             :                                                                         // we should calculate it exactly from layoutRect or font
    1964             :                                         ::vcl::unotools::pointFromB2DPoint ( point ),
    1965             :                                         ::Size(),
    1966             :                                         ::Color(),
    1967             :                                         ::Size(),
    1968             :                                         ::Color(),
    1969             :                                         text,
    1970             :                                         0,
    1971             :                                         stringLength,
    1972             :                                         NULL,
    1973             :                                         rFactoryParms.mrVDev,
    1974             :                                         rFactoryParms.mrCanvas,
    1975             :                                         rState,
    1976             :                                         rFactoryParms.mrParms,
    1977           0 :                                         false ) );
    1978           0 :                                 if( pTextAction )
    1979             :                                 {
    1980             :                                     SAL_INFO("cppcanvas.emf", "EMF+\t\tadd text action");
    1981             : 
    1982             :                                     maActions.push_back(
    1983             :                                                         MtfAction(
    1984             :                                                                   pTextAction,
    1985           0 :                                                                   rFactoryParms.mrCurrActionIndex ) );
    1986             : 
    1987           0 :                                     rFactoryParms.mrCurrActionIndex += pTextAction->getActionCount()-1;
    1988           0 :                                 }
    1989             :                             } else {
    1990             :                                 SAL_INFO("cppcanvas.emf", "EMF+ DrawString TODO - drawing with brush not yet supported");
    1991             :                             }
    1992             :                         }
    1993           0 :                         break;
    1994             :                     case EmfPlusRecordTypeSetPageTransform:
    1995           0 :                         rMF.ReadFloat( fPageScale );
    1996             : 
    1997             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetPageTransform");
    1998             :                         SAL_INFO("cppcanvas.emf", "EMF+\tscale: " << fPageScale << " unit: " << flags);
    1999             :                         SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    2000           0 :                         break;
    2001             :                     case EmfPlusRecordTypeSetRenderingOrigin:
    2002           0 :                         rMF.ReadInt32( nOriginX ).ReadInt32( nOriginY );
    2003             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetRenderingOrigin");
    2004             :                         SAL_INFO("cppcanvas.emf", "EMF+\torigin [x,y]: " << nOriginX << "," << nOriginY);
    2005           0 :                         break;
    2006             :                     case EmfPlusRecordTypeSetTextRenderingHint:
    2007             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetTextRenderingHint");
    2008             :                         SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    2009           0 :                         break;
    2010             :                     case EmfPlusRecordTypeSetAntiAliasMode:
    2011             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetAntiAliasMode");
    2012             :                         SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    2013           0 :                         break;
    2014             :                     case EmfPlusRecordTypeSetInterpolationMode:
    2015             :                         SAL_INFO("cppcanvas.emf", "EMF+ InterpolationMode");
    2016             :                         SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    2017           0 :                         break;
    2018             :                     case EmfPlusRecordTypeSetPixelOffsetMode:
    2019             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetPixelOffsetMode");
    2020             :                         SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    2021           0 :                         break;
    2022             :                     case EmfPlusRecordTypeSetCompositingQuality:
    2023             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetCompositingQuality");
    2024             :                         SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    2025           0 :                         break;
    2026             :                     case EmfPlusRecordTypeSave:
    2027             :                     {
    2028             :                         sal_uInt32 stackIndex;
    2029             : 
    2030           0 :                         rMF.ReadUInt32( stackIndex );
    2031             : 
    2032             :                         SAL_INFO("cppcanvas.emf", "EMF+ Save stack index: " << stackIndex);
    2033             : 
    2034           0 :                         GraphicStatePush( mGSStack, stackIndex, rState );
    2035             : 
    2036           0 :                         break;
    2037             :                     }
    2038             :                     case EmfPlusRecordTypeRestore:
    2039             :                     {
    2040             :                         sal_uInt32 stackIndex;
    2041             : 
    2042           0 :                         rMF.ReadUInt32( stackIndex );
    2043             : 
    2044             :                         SAL_INFO("cppcanvas.emf", "EMF+ Restore stack index: " << stackIndex);
    2045             : 
    2046           0 :                         GraphicStatePop( mGSStack, stackIndex, rState );
    2047             : 
    2048           0 :                         break;
    2049             :                     }
    2050             :                     case EmfPlusRecordTypeBeginContainerNoParams:
    2051             :                     {
    2052             :                         sal_uInt32 stackIndex;
    2053             : 
    2054           0 :                         rMF.ReadUInt32( stackIndex );
    2055             : 
    2056             :                         SAL_INFO("cppcanvas.emf", "EMF+ Begin Container No Params stack index: " << stackIndex);
    2057             : 
    2058           0 :                         GraphicStatePush( mGSContainerStack, stackIndex, rState );
    2059             :                     }
    2060           0 :                     break;
    2061             :                     case EmfPlusRecordTypeEndContainer:
    2062             :                     {
    2063             :                         sal_uInt32 stackIndex;
    2064             : 
    2065           0 :                         rMF.ReadUInt32( stackIndex );
    2066             : 
    2067             :                         SAL_INFO("cppcanvas.emf", "EMF+ End Container stack index: " << stackIndex);
    2068             : 
    2069           0 :                         GraphicStatePop( mGSContainerStack, stackIndex, rState );
    2070             :                     }
    2071           0 :                     break;
    2072             :                     case EmfPlusRecordTypeSetWorldTransform: {
    2073             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetWorldTransform");
    2074           0 :                         XForm transform;
    2075           0 :                         ReadXForm( rMF, transform );
    2076           0 :                         aWorldTransform.Set (transform);
    2077             :                         SAL_INFO("cppcanvas.emf",
    2078             :                                 "EMF+\tm11: " << aWorldTransform.eM11 << "\tm12: " << aWorldTransform.eM12 <<
    2079             :                                 "\tm21: " << aWorldTransform.eM21 << "\tm22: " << aWorldTransform.eM22 <<
    2080             :                                 "\tdx: "  << aWorldTransform.eDx  << "\tdy: "  << aWorldTransform.eDy);
    2081           0 :                         break;
    2082             :                     }
    2083             :                     case EmfPlusRecordTypeResetWorldTransform:
    2084             :                         SAL_INFO("cppcanvas.emf", "EMF+ ResetWorldTransform");
    2085           0 :                         aWorldTransform.SetIdentity ();
    2086           0 :                         break;
    2087             :                     case EmfPlusRecordTypeMultiplyWorldTransform: {
    2088             :                         SAL_INFO("cppcanvas.emf", "EMF+ MultiplyWorldTransform");
    2089           0 :                         XForm transform;
    2090           0 :                         ReadXForm( rMF, transform );
    2091             : 
    2092             :                         SAL_INFO("cppcanvas.emf",
    2093             :                                 "EMF+\tmatrix m11: " << transform.eM11 << "m12: " << transform.eM12 <<
    2094             :                                 "EMF+\tm21: "        << transform.eM21 << "m22: " << transform.eM22 <<
    2095             :                                 "EMF+\tdx: "         << transform.eDx  << "dy: "  << transform.eDy);
    2096             : 
    2097           0 :                         if (flags & 0x2000)  // post multiply
    2098           0 :                             aWorldTransform.Multiply (transform);
    2099             :                         else {               // pre multiply
    2100           0 :                             transform.Multiply (aWorldTransform);
    2101           0 :                             aWorldTransform.Set (transform);
    2102             :                         }
    2103             :                         SAL_INFO("cppcanvas.emf",
    2104             :                                 "EMF+\tm11: " << aWorldTransform.eM11 << "m12: " << aWorldTransform.eM12 <<
    2105             :                                 "EMF+\tm21: " << aWorldTransform.eM21 << "m22: " << aWorldTransform.eM22 <<
    2106             :                                 "EMF+\tdx: "  << aWorldTransform.eDx  << "dy: "  << aWorldTransform.eDy);
    2107           0 :                         break;
    2108             :                     }
    2109             :                     case EmfPlusRecordTypeSetClipRect:
    2110             :                         {
    2111           0 :                             int combineMode = (flags >> 8) & 0xf;
    2112             : 
    2113             :                             SAL_INFO("cppcanvas.emf", "EMF+ SetClipRect combine mode: " << combineMode);
    2114             : #if OSL_DEBUG_LEVEL > 1
    2115             :                             if (combineMode > 1) {
    2116             :                                 SAL_INFO ("cppcanvas.emf", "EMF+ TODO combine mode > 1");
    2117             :                             }
    2118             : #endif
    2119             : 
    2120             :                             float dx, dy, dw, dh;
    2121             : 
    2122           0 :                             ReadRectangle (rMF, dx, dy, dw, dh, false);
    2123             : 
    2124             :                             SAL_INFO("cppcanvas.emf", "EMF+ RectData: " << dx << "," << dy << " " << dw << "x" << dh);
    2125             : 
    2126           0 :                             B2DPoint mappedPoint (Map (dx, dy));
    2127           0 :                             B2DSize mappedSize( MapSize (dw, dh));
    2128             : 
    2129             :                             ::basegfx::B2DPolyPolygon polyPolygon( ::basegfx::B2DPolygon( ::basegfx::tools::createPolygonFromRect( ::basegfx::B2DRectangle( mappedPoint.getX(), mappedPoint.getY(),
    2130           0 :                                                                                                                                                             mappedPoint.getX() + mappedSize.getX(),
    2131           0 :                                                                                                                                                             mappedPoint.getY() + mappedSize.getY() ) ) ) );
    2132           0 :                             polyPolygon.transform(rState.mapModeTransform);
    2133             : 
    2134           0 :                             updateClipping (polyPolygon, rFactoryParms, combineMode == 1);
    2135             : 
    2136           0 :                             break;
    2137             :                         }
    2138             :                     case EmfPlusRecordTypeSetClipPath:
    2139             :                         {
    2140           0 :                             int combineMode = (flags >> 8) & 0xf;
    2141             : 
    2142             :                             SAL_INFO("cppcanvas.emf", "EMF+ SetClipPath combine mode: " << combineMode);
    2143             :                             SAL_INFO("cppcanvas.emf", "EMF+\tpath in slot: " << (flags & 0xff));
    2144             : 
    2145           0 :                             EMFPPath& path = *(EMFPPath*) aObjects [flags & 0xff];
    2146           0 :                             ::basegfx::B2DPolyPolygon& clipPoly (path.GetPolygon (*this));
    2147             : 
    2148           0 :                             clipPoly.transform (rState.mapModeTransform);
    2149           0 :                             switch (combineMode)
    2150             :                             {
    2151             :                             case EmfPlusCombineModeReplace:
    2152             :                             case EmfPlusCombineModeIntersect:
    2153             :                             case EmfPlusCombineModeUnion: // Is this, EmfPlusCombineModeXOR and EmfPlusCombineModeComplement correct?
    2154             :                             case EmfPlusCombineModeXOR:
    2155             :                             case EmfPlusCombineModeComplement:
    2156           0 :                                 updateClipping (clipPoly, rFactoryParms, combineMode == 1);
    2157           0 :                                 break;
    2158             :                             case EmfPlusCombineModeExclude:
    2159             :                                 // Not doing anything is better then including exactly what we wanted to exclude.
    2160           0 :                                 break;
    2161             :                             }
    2162             : 
    2163           0 :                             break;
    2164             :                         }
    2165             :                     case EmfPlusRecordTypeSetClipRegion: {
    2166           0 :                         int combineMode = (flags >> 8) & 0xf;
    2167             : 
    2168             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetClipRegion");
    2169             :                         SAL_INFO("cppcanvas.emf", "EMF+\tregion in slot: " << (flags & 0xff) << " combine mode: " << combineMode);
    2170           0 :                         EMFPRegion *region = (EMFPRegion*)aObjects [flags & 0xff];
    2171             : 
    2172             :                         // reset clip
    2173           0 :                         if (region && region->parts == 0 && region->initialState == EmfPlusRegionInitialStateInfinite) {
    2174           0 :                             updateClipping (::basegfx::B2DPolyPolygon (), rFactoryParms, combineMode == 1);
    2175             :                         } else {
    2176             :                             SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    2177             :                         }
    2178           0 :                         break;
    2179             :                     }
    2180             :                     case EmfPlusRecordTypeDrawDriverString: {
    2181             :                         SAL_INFO("cppcanvas.emf", "EMF+ DrawDriverString, flags: 0x" << std::hex << flags << std::dec);
    2182             :                         sal_uInt32 brushIndexOrColor;
    2183             :                         sal_uInt32 optionFlags;
    2184             :                         sal_uInt32 hasMatrix;
    2185             :                         sal_uInt32 glyphsCount;
    2186             : 
    2187           0 :                         rMF.ReadUInt32( brushIndexOrColor ).ReadUInt32( optionFlags ).ReadUInt32( hasMatrix ).ReadUInt32( glyphsCount );
    2188             : 
    2189             :                         SAL_INFO("cppcanvas.emf", "EMF+\t: " << ((flags & 0x8000) ? "color" : "brush index") << " 0x" << std::hex << brushIndexOrColor << std::dec);
    2190             :                         SAL_INFO("cppcanvas.emf", "EMF+\toption flags: 0x" << std::hex << optionFlags << std::dec);
    2191             :                         SAL_INFO("cppcanvas.emf", "EMF+\thas matrix: " << hasMatrix);
    2192             :                         SAL_INFO("cppcanvas.emf", "EMF+\tglyphs: " << glyphsCount);
    2193             : 
    2194           0 :                         if( ( optionFlags & 1 ) && glyphsCount > 0 ) {
    2195           0 :                             float *charsPosX = new float[glyphsCount];
    2196           0 :                             float *charsPosY = new float[glyphsCount];
    2197             : 
    2198           0 :                             OUString text = read_uInt16s_ToOUString(rMF, glyphsCount);
    2199             : 
    2200           0 :                             for( sal_uInt32 i=0; i<glyphsCount; i++) {
    2201           0 :                                 rMF.ReadFloat( charsPosX[i] ).ReadFloat( charsPosY[i] );
    2202             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tglyphPosition[" << i << "]: " << charsPosX[i] << "," << charsPosY[i]);
    2203             :                             }
    2204             : 
    2205           0 :                             XForm transform;
    2206           0 :                             if( hasMatrix ) {
    2207           0 :                                 ReadXForm( rMF, transform );
    2208             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tmatrix: " << transform.eM11 << ", " << transform.eM12 << ", " << transform.eM21 << ", " << transform.eM22 << ", " << transform.eDx << ", " << transform.eDy);
    2209             :                             }
    2210             : 
    2211             :                             // add the text action
    2212           0 :                             setFont (flags & 0xff, rFactoryParms, rState);
    2213             : 
    2214           0 :                             if( flags & 0x8000 )
    2215           0 :                                 rState.textColor = COLOR( brushIndexOrColor );
    2216             : 
    2217           0 :                             ::basegfx::B2DPoint point( Map( charsPosX[0], charsPosY[0] ) );
    2218             : 
    2219             :                             ActionSharedPtr pTextAction(
    2220             :                                     TextActionFactory::createTextAction(
    2221             :                                         ::vcl::unotools::pointFromB2DPoint ( point ),
    2222             :                                         ::Size(),
    2223             :                                         ::Color(),
    2224             :                                         ::Size(),
    2225             :                                         ::Color(),
    2226             :                                         text,
    2227             :                                         0,
    2228             :                                         glyphsCount,
    2229             :                                         NULL,
    2230             :                                         rFactoryParms.mrVDev,
    2231             :                                         rFactoryParms.mrCanvas,
    2232             :                                         rState,
    2233             :                                         rFactoryParms.mrParms,
    2234           0 :                                         false ) );
    2235             : 
    2236           0 :                             if( pTextAction )
    2237             :                             {
    2238             :                                 SAL_INFO("cppcanvas.emf", "EMF+\t\tadd text action");
    2239             : 
    2240             :                                 maActions.push_back(
    2241             :                                         MtfAction(
    2242             :                                             pTextAction,
    2243           0 :                                             rFactoryParms.mrCurrActionIndex ) );
    2244             : 
    2245           0 :                                 rFactoryParms.mrCurrActionIndex += pTextAction->getActionCount()-1;
    2246             :                             }
    2247             : 
    2248           0 :                             delete[] charsPosX;
    2249           0 :                             delete[] charsPosY;
    2250             :                         } else {
    2251             :                             SAL_INFO("cppcanvas.emf", "EMF+\tTODO: fonts (non-unicode glyphs chars)");
    2252             :                         }
    2253             : 
    2254           0 :                         break;
    2255             :                     }
    2256             :                     default:
    2257             :                         SAL_INFO("cppcanvas.emf", "EMF+ unhandled record type: " << type);
    2258             :                         SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    2259             :                     }
    2260             :                 }
    2261             : 
    2262           0 :                 rMF.Seek (next);
    2263             : 
    2264           0 :                 if (size <= length)
    2265             :                 {
    2266           0 :                     length -= size;
    2267             :                 }
    2268             :                 else
    2269             :                 {
    2270             :                     SAL_WARN("cppcanvas.emf", "ImplRenderer::processEMFPlus: "
    2271             :                             "size " << size << " > length " << length);
    2272           0 :                     length = 0;
    2273             :                 }
    2274           0 :             }
    2275           0 :         }
    2276             :     }
    2277             : }
    2278             : 
    2279             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10