LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/cppcanvas/source/mtfrenderer - emfplus.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1 752 0.1 %
Date: 2013-07-09 Functions: 2 41 4.9 %
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/b2dpolygon.hxx>
      32             : #include <basegfx/polygon/b2dpolygontools.hxx>
      33             : #include <basegfx/polygon/b2dpolypolygon.hxx>
      34             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      35             : #include <vcl/canvastools.hxx>
      36             : #include <rtl/ustring.hxx>
      37             : #include <sal/alloca.h>
      38             : 
      39             : #include <com/sun/star/rendering/XCanvas.hpp>
      40             : #include <com/sun/star/rendering/TexturingMode.hpp>
      41             : 
      42             : #include <bitmapaction.hxx>
      43             : #include <implrenderer.hxx>
      44             : #include <outdevstate.hxx>
      45             : #include <polypolyaction.hxx>
      46             : #include <textaction.hxx>
      47             : #include <stdio.h>
      48             : 
      49             : #define EmfPlusRecordTypeHeader 16385
      50             : #define EmfPlusRecordTypeEndOfFile 16386
      51             : #define EmfPlusRecordTypeGetDC 16388
      52             : #define EmfPlusRecordTypeObject 16392
      53             : #define EmfPlusRecordTypeFillRects 16394
      54             : #define EmfPlusRecordTypeFillPolygon 16396
      55             : #define EmfPlusRecordTypeDrawLines 16397
      56             : #define EmfPlusRecordTypeFillEllipse 16398
      57             : #define EmfPlusRecordTypeDrawEllipse 16399
      58             : #define EmfPlusRecordTypeFillPie 16400
      59             : #define EmfPlusRecordTypeFillPath 16404
      60             : #define EmfPlusRecordTypeDrawPath 16405
      61             : #define EmfPlusRecordTypeDrawImage 16410
      62             : #define EmfPlusRecordTypeDrawImagePoints 16411
      63             : #define EmfPlusRecordTypeDrawString 16412
      64             : #define EmfPlusRecordTypeSetRenderingOrigin 16413
      65             : #define EmfPlusRecordTypeSetAntiAliasMode 16414
      66             : #define EmfPlusRecordTypeSetTextRenderingHint 16415
      67             : #define EmfPlusRecordTypeSetInterpolationMode 16417
      68             : #define EmfPlusRecordTypeSetPixelOffsetMode 16418
      69             : #define EmfPlusRecordTypeSetCompositingQuality 16420
      70             : #define EmfPlusRecordTypeSave 16421
      71             : #define EmfPlusRecordTypeRestore 16422
      72             : #define EmfPlusRecordTypeBeginContainerNoParams 16424
      73             : #define EmfPlusRecordTypeEndContainer 16425
      74             : #define EmfPlusRecordTypeSetWorldTransform 16426
      75             : #define EmfPlusRecordTypeResetWorldTransform 16427
      76             : #define EmfPlusRecordTypeMultiplyWorldTransform 16428
      77             : #define EmfPlusRecordTypeSetPageTransform 16432
      78             : #define EmfPlusRecordTypeSetClipRect 16434
      79             : #define EmfPlusRecordTypeSetClipPath 16435
      80             : #define EmfPlusRecordTypeSetClipRegion 16436
      81             : #define EmfPlusRecordTypeDrawDriverString 16438
      82             : 
      83             : #define EmfPlusObjectTypeBrush 0x100
      84             : #define EmfPlusObjectTypePen 0x200
      85             : #define EmfPlusObjectTypePath 0x300
      86             : #define EmfPlusObjectTypeRegion 0x400
      87             : #define EmfPlusObjectTypeImage 0x500
      88             : #define EmfPlusObjectTypeFont 0x600
      89             : 
      90             : #define EmfPlusRegionInitialStateInfinite 0x10000003
      91             : 
      92             : using namespace ::com::sun::star;
      93             : using namespace ::basegfx;
      94             : 
      95             : namespace cppcanvas
      96             : {
      97             :     namespace internal
      98             :     {
      99             : 
     100             : #if OSL_DEBUG_LEVEL > 1
     101             :         void dumpWords (SvStream& s, int i)
     102             :         {
     103             :             sal_uInt32 pos = s.Tell ();
     104             :             sal_Int16 data;
     105             :             SAL_INFO ("cppcanvas.emf", "EMF+ dumping words");
     106             :             for (; i > 0; i --) {
     107             :                 s >> data;
     108             :                 SAL_INFO ("cppcanvas.emf", "EMF+\tdata: " << std::hex << data << std::dec);
     109             :             }
     110             :             SAL_INFO ("cppcanvas.emf", "EMF+ end dumping words");
     111             :             s.Seek (pos);
     112             :         }
     113             : #endif
     114             : 
     115             :         struct EMFPPath : public EMFPObject
     116             :         {
     117             :             ::basegfx::B2DPolyPolygon    aPolygon;
     118             :             sal_Int32                    nPoints;
     119             :             float*                       pPoints;
     120             :             sal_uInt8*                   pPointTypes;
     121             : 
     122             :         public:
     123           0 :             EMFPPath (sal_Int32 _nPoints, bool bLines = false)
     124           0 :             {
     125           0 :                 if( _nPoints<0 || sal_uInt32(_nPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
     126           0 :                     _nPoints = SAL_MAX_INT32/(2*sizeof(float));
     127           0 :                 nPoints = _nPoints;
     128           0 :                 pPoints = new float [nPoints*2];
     129           0 :                 if (!bLines)
     130           0 :                     pPointTypes = new sal_uInt8 [_nPoints];
     131             :                 else
     132           0 :                     pPointTypes = NULL;
     133           0 :             }
     134             : 
     135           0 :             ~EMFPPath ()
     136           0 :             {
     137           0 :                 delete [] pPoints;
     138           0 :                 delete [] pPointTypes;
     139           0 :             }
     140             : 
     141             :             // TODO: remove rR argument when debug code is not longer needed
     142           0 :             void Read (SvStream& s, sal_uInt32 pathFlags, ImplRenderer& rR)
     143             :             {
     144           0 :                 for (int i = 0; i < nPoints; i ++) {
     145           0 :                     if (pathFlags & 0x4000) {
     146             :                         // points are stored in short 16bit integer format
     147             :                         sal_uInt16 x, y;
     148             : 
     149           0 :                         s >> x >> y;
     150             :                         SAL_INFO ("cppcanvas.emf", "EMF+\tpoint [x,y]: " << x << "," << y);
     151           0 :                         pPoints [i*2] = x;
     152           0 :                         pPoints [i*2 + 1] = y;
     153             :                     } else {
     154             :                         // points are stored in Single (float) format
     155           0 :                         s >> pPoints [i*2] >> pPoints [i*2 + 1];
     156             :                         SAL_INFO ("cppcanvas.emf", "EMF+\tpoint [x,y]: " << pPoints [i*2] << "," << pPoints [i*2 + 1]);
     157             :                     }
     158             :                 }
     159             : 
     160           0 :                 if (pPointTypes)
     161           0 :                     for (int i = 0; i < nPoints; i ++) {
     162           0 :                         s >> pPointTypes [i];
     163             :                         SAL_INFO ("cppcanvas.emf", "EMF+\tpoint type: " << (int)pPointTypes [i]);
     164             :                     }
     165             : 
     166           0 :                 aPolygon.clear ();
     167             : 
     168             : #if OSL_DEBUG_LEVEL > 1
     169             :                 const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (GetPolygon (rR)));
     170             : 
     171             :                 SAL_INFO ("cppcanvas.emf",
     172             :                           "EMF+\tpolygon bounding box: " << aBounds.getMinX () << "," << aBounds.getMinY () << aBounds.getWidth () << "x" << aBounds.getHeight () << " (mapped)");
     173             : #else
     174             :                 (void) rR; // avoid warnings
     175             : #endif
     176           0 :             }
     177             : 
     178           0 :             ::basegfx::B2DPolyPolygon& GetPolygon (ImplRenderer& rR, bool bMapIt = true)
     179             :             {
     180           0 :                 ::basegfx::B2DPolygon polygon;
     181             : 
     182           0 :                 aPolygon.clear ();
     183             : 
     184           0 :                 int last_normal = 0, p = 0;
     185           0 :                 ::basegfx::B2DPoint prev, mapped;
     186           0 :                 bool hasPrev = false;
     187           0 :                 for (int i = 0; i < nPoints; i ++) {
     188           0 :                     if (p && pPointTypes && (pPointTypes [i] == 0)) {
     189           0 :                         aPolygon.append (polygon);
     190           0 :                         last_normal = i;
     191           0 :                         p = 0;
     192           0 :                         polygon.clear ();
     193             :                     }
     194             : 
     195           0 :                     if (bMapIt)
     196           0 :                         mapped = rR.Map (pPoints [i*2], pPoints [i*2 + 1]);
     197             :                     else
     198           0 :                         mapped = ::basegfx::B2DPoint (pPoints [i*2], pPoints [i*2 + 1]);
     199           0 :                     if (pPointTypes) {
     200           0 :                         if ((pPointTypes [i] & 0x07) == 3) {
     201           0 :                             if (((i - last_normal )% 3) == 1) {
     202           0 :                                 polygon.setNextControlPoint (p - 1, mapped);
     203             :                                 SAL_INFO ("cppcanvas.emf", "polygon append  next: " << p - 1 << " mapped: " << mapped.getX () << "," << mapped.getY ());
     204           0 :                                 continue;
     205           0 :                             } else if (((i - last_normal) % 3) == 2) {
     206           0 :                                 prev = mapped;
     207           0 :                                 hasPrev = true;
     208           0 :                                 continue;
     209             :                             }
     210             :                         } else
     211           0 :                             last_normal = i;
     212             :                     }
     213           0 :                     polygon.append (mapped);
     214             :                     SAL_INFO ("cppcanvas.emf", "polygon append point: " << pPoints [i*2] << "," << pPoints [i*2 + 1] << " mapped: " << mapped.getX () << ":" << mapped.getY ());
     215           0 :                     if (hasPrev) {
     216           0 :                         polygon.setPrevControlPoint (p, prev);
     217             :                         SAL_INFO ("cppcanvas.emf", "polygon append  prev: " << p << " mapped: " << prev.getX () << "," << prev.getY ());
     218           0 :                         hasPrev = false;
     219             :                     }
     220           0 :                     p ++;
     221           0 :                     if (pPointTypes && (pPointTypes [i] & 0x80)) { // closed polygon
     222           0 :                         polygon.setClosed (true);
     223           0 :                         aPolygon.append (polygon);
     224             :                         SAL_INFO ("cppcanvas.emf", "close polygon");
     225           0 :                         last_normal = i + 1;
     226           0 :                         p = 0;
     227           0 :                         polygon.clear ();
     228             :                     }
     229             :                 }
     230             : 
     231           0 :                 if (polygon.count ()) {
     232           0 :                     aPolygon.append (polygon);
     233             : 
     234             : #if OSL_DEBUG_LEVEL > 1
     235             :                     for (unsigned int i=0; i<aPolygon.count(); i++) {
     236             :                         polygon = aPolygon.getB2DPolygon(i);
     237             :                         SAL_INFO ("cppcanvas.emf", "polygon: " << i);
     238             :                         for (unsigned int j=0; j<polygon.count(); j++) {
     239             :                             ::basegfx::B2DPoint point = polygon.getB2DPoint(j);
     240             :                             SAL_INFO ("cppcanvas.emf", "point: " << point.getX() << "," << point.getY());
     241             :                             if (polygon.isPrevControlPointUsed(j)) {
     242             :                                 point = polygon.getPrevControlPoint(j);
     243             :                                 SAL_INFO ("cppcanvas.emf", "prev: " << point.getX() << "," << point.getY());
     244             :                             }
     245             :                             if (polygon.isNextControlPointUsed(j)) {
     246             :                                 point = polygon.getNextControlPoint(j);
     247             :                                 SAL_INFO ("cppcanvas.emf", "next: " << point.getX() << "," << point.getY());
     248             :                             }
     249             :                         }
     250             :                     }
     251             : #endif
     252             :                 }
     253             : 
     254           0 :                 return aPolygon;
     255             :             }
     256             :         };
     257             : 
     258             :         struct EMFPRegion : public EMFPObject
     259             :         {
     260             :             sal_Int32 parts;
     261             :             sal_Int32 *combineMode;
     262             :             sal_Int32 initialState;
     263             :             EMFPPath *initialPath;
     264             :             float ix, iy, iw, ih;
     265             : 
     266           0 :             EMFPRegion ()
     267           0 :             {
     268           0 :                 combineMode = NULL;
     269           0 :                 initialPath = NULL;
     270           0 :             }
     271             : 
     272           0 :             ~EMFPRegion ()
     273           0 :             {
     274           0 :                 if (combineMode) {
     275           0 :                     delete [] combineMode;
     276           0 :                     combineMode = NULL;
     277             :                 }
     278           0 :                 if (initialPath) {
     279           0 :                     delete initialPath;
     280           0 :                     initialPath = NULL;
     281             :                 }
     282           0 :             }
     283             : 
     284           0 :             void Read (SvStream& s)
     285             :             {
     286             :                 sal_uInt32 header;
     287             : 
     288           0 :                 s >> header >> parts;
     289             : 
     290             :                 SAL_INFO ("cppcanvas.emf", "EMF+\tregion");
     291             :                 SAL_INFO ("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " parts: " << parts << std::dec );
     292             : 
     293           0 :                 if (parts) {
     294           0 :                     if( parts<0 || sal_uInt32(parts)>SAL_MAX_INT32/sizeof(sal_Int32) )
     295           0 :                         parts = SAL_MAX_INT32/sizeof(sal_Int32);
     296             : 
     297           0 :                     combineMode = new sal_Int32 [parts];
     298             : 
     299           0 :                     for (int i = 0; i < parts; i ++) {
     300           0 :                         s >> combineMode [i];
     301             :                         SAL_INFO ("cppcanvas.emf", "EMF+\tcombine mode [" << i << "]: 0x" << std::hex << combineMode [i] << std::dec);
     302             :                     }
     303             :                 }
     304             : 
     305           0 :                 s >> initialState;
     306             :                 SAL_INFO ("cppcanvas.emf", "EMF+\tinitial state: 0x" << std::hex << initialState << std::dec);
     307           0 :             }
     308             :         };
     309             : 
     310             :         struct EMFPBrush : public EMFPObject
     311             :         {
     312             :             ::Color solidColor;
     313             :             sal_uInt32 type;
     314             :             sal_uInt32 additionalFlags;
     315             : 
     316             :             /* linear gradient */
     317             :             sal_Int32 wrapMode;
     318             :             float areaX, areaY, areaWidth, areaHeight;
     319             :             ::Color secondColor; // first color is stored in solidColor;
     320             :             XForm transformation;
     321             :             bool hasTransformation;
     322             :             sal_Int32 blendPoints;
     323             :             float* blendPositions;
     324             :             float* blendFactors;
     325             :             sal_Int32 colorblendPoints;
     326             :             float* colorblendPositions;
     327             :             ::Color* colorblendColors;
     328             :             sal_Int32 surroundColorsNumber;
     329             :             ::Color* surroundColors;
     330             :             EMFPPath *path;
     331             : 
     332             :         public:
     333           0 :             EMFPBrush ()
     334           0 :             {
     335           0 :                 blendPositions = NULL;
     336           0 :                 colorblendPositions = NULL;
     337           0 :                 colorblendColors = NULL;
     338           0 :                 surroundColors = NULL;
     339           0 :                 path = NULL;
     340           0 :                 hasTransformation = false;
     341           0 :             }
     342             : 
     343           0 :             ~EMFPBrush ()
     344           0 :             {
     345           0 :                 if (blendPositions != NULL) {
     346           0 :                     delete[] blendPositions;
     347           0 :                     blendPositions = NULL;
     348             :                 }
     349           0 :                 if (colorblendPositions != NULL) {
     350           0 :                     delete[] colorblendPositions;
     351           0 :                     colorblendPositions = NULL;
     352             :                 }
     353           0 :                 if (colorblendColors != NULL) {
     354           0 :                     delete[] colorblendColors;
     355           0 :                     colorblendColors = NULL;
     356             :                 }
     357           0 :                 if (surroundColors != NULL) {
     358           0 :                     delete[] surroundColors;
     359           0 :                     surroundColors = NULL;
     360             :                 }
     361           0 :                 if (path) {
     362           0 :                     delete path;
     363           0 :                     path = NULL;
     364             :                 }
     365           0 :             }
     366             : 
     367             :             sal_uInt32 GetType() const { return type; }
     368           0 :             const ::Color& GetColor() const { return solidColor; }
     369             : 
     370           0 :             void Read (SvStream& s, ImplRenderer& rR)
     371             :             {
     372             :                 sal_uInt32 header;
     373             : 
     374           0 :                 s >> header >> type;
     375             : 
     376             :                 SAL_INFO ("cppcanvas.emf", "EMF+\tbrush");
     377             :                 SAL_INFO ("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec);
     378             : 
     379           0 :                 switch (type) {
     380             :                 case 0:
     381             :                     {
     382             :                         sal_uInt32 color;
     383             : 
     384           0 :                         s >> color;
     385           0 :                         solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
     386             :                         SAL_INFO ("cppcanvas.emf", "EMF+\tsolid color: 0x" << std::hex << color << std::dec);
     387             : 
     388           0 :                         break;
     389             :                     }
     390             :                 // path gradient
     391             :                 case 3:
     392             :                     {
     393           0 :                         s >> additionalFlags >> wrapMode;
     394             : 
     395             :                         SAL_INFO ("cppcanvas.emf", "EMF+\tpath gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec);
     396             : 
     397             :                         sal_uInt32 color;
     398             : 
     399           0 :                         s >> color;
     400           0 :                         solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
     401             :                         SAL_INFO("cppcanvas.emf", "EMF+\tcenter color: 0x" << std::hex << color << std::dec);
     402             : 
     403           0 :                         s >> areaX >> areaY;
     404             :                         SAL_INFO("cppcanvas.emf", "EMF+\tcenter point: " << areaX << "," << areaY);
     405             : 
     406           0 :                         s >> surroundColorsNumber;
     407             :                         SAL_INFO("cppcanvas.emf", "EMF+\tsurround colors: " << surroundColorsNumber);
     408             : 
     409           0 :                         if( surroundColorsNumber<0 || sal_uInt32(surroundColorsNumber)>SAL_MAX_INT32/sizeof(::Color) )
     410           0 :                             surroundColorsNumber = SAL_MAX_INT32/sizeof(::Color);
     411             : 
     412           0 :                         surroundColors = new ::Color [surroundColorsNumber];
     413           0 :                         for (int i = 0; i < surroundColorsNumber; i++) {
     414           0 :                             s >> color;
     415           0 :                             surroundColors[i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
     416           0 :                             if (i == 0)
     417           0 :                                 secondColor = surroundColors [0];
     418             :                             SAL_INFO("cppcanvas.emf", "EMF+\tsurround color[" << i << "]: 0x" << std::hex << color << std::dec);
     419             :                         }
     420             : 
     421           0 :                         if (additionalFlags & 0x01) {
     422             :                             sal_Int32 pathLength;
     423             : 
     424           0 :                             s >> pathLength;
     425             :                             SAL_INFO("cppcanvas.emf", "EMF+\tpath length: " << pathLength);
     426             : 
     427           0 :                             sal_uInt32 pos = s.Tell ();
     428             : #if OSL_DEBUG_LEVEL > 1
     429             :                             dumpWords (s, 32);
     430             : #endif
     431             : 
     432             :                             sal_uInt32 pathHeader;
     433             :                             sal_Int32 pathPoints, pathFlags;
     434           0 :                             s >> pathHeader >> pathPoints >> pathFlags;
     435             : 
     436             :                             SAL_INFO("cppcanvas.emf", "EMF+\tpath (brush path gradient)");
     437             :                             SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec );
     438             : 
     439           0 :                             path = new EMFPPath (pathPoints);
     440           0 :                             path->Read (s, pathFlags, rR);
     441             : 
     442           0 :                             s.Seek (pos + pathLength);
     443             : 
     444           0 :                             const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (path->GetPolygon (rR, false)));
     445           0 :                             areaWidth = aBounds.getWidth ();
     446           0 :                             areaHeight = aBounds.getHeight ();
     447             : 
     448             :                             SAL_INFO("cppcanvas.emf", "EMF+\tpolygon bounding box: " << aBounds.getMinX () << "," << aBounds.getMinY () << " " << aBounds.getWidth () << "x" << aBounds.getHeight ());
     449             : 
     450             : 
     451           0 :                         if (additionalFlags & 0x02) {
     452             :                             SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation");
     453           0 :                             s >> transformation;
     454           0 :                             hasTransformation = true;
     455             :                             SAL_INFO("cppcanvas.emf",
     456             :                                     "EMF+\tm11: "   << transformation.eM11 << " m12: " << transformation.eM12 <<
     457             :                                     "\nEMF+\tm21: " << transformation.eM21 << " m22: " << transformation.eM22 <<
     458             :                                     "\nEMF+\tdx: "  << transformation.eDx  << " dy: "  << transformation.eDy);
     459             : 
     460             :                         }
     461           0 :                         if (additionalFlags & 0x08) {
     462           0 :                             s >> blendPoints;
     463             :                             SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints);
     464           0 :                             if( blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
     465           0 :                                 blendPoints = SAL_MAX_INT32/(2*sizeof(float));
     466           0 :                             blendPositions = new float [2*blendPoints];
     467           0 :                             blendFactors = blendPositions + blendPoints;
     468           0 :                             for (int i=0; i < blendPoints; i ++) {
     469           0 :                                 s >> blendPositions [i];
     470             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions [i]);
     471             :                             }
     472           0 :                             for (int i=0; i < blendPoints; i ++) {
     473           0 :                                 s >> blendFactors [i];
     474             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors [i]);
     475             :                             }
     476             :                         }
     477             : 
     478           0 :                         if (additionalFlags & 0x04) {
     479           0 :                             s >> colorblendPoints;
     480             :                             SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints);
     481           0 :                             if( colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(float) )
     482           0 :                                 colorblendPoints = SAL_MAX_INT32/sizeof(float);
     483           0 :                             if( sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(::Color) )
     484           0 :                                 colorblendPoints = SAL_MAX_INT32/sizeof(::Color);
     485           0 :                             colorblendPositions = new float [colorblendPoints];
     486           0 :                             colorblendColors = new ::Color [colorblendPoints];
     487           0 :                             for (int i=0; i < colorblendPoints; i ++) {
     488           0 :                                 s >> colorblendPositions [i];
     489             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions [i]);
     490             :                             }
     491           0 :                             for (int i=0; i < colorblendPoints; i ++) {
     492           0 :                                 s >> color;
     493           0 :                                 colorblendColors [i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
     494             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec);
     495             :                             }
     496             :                         }
     497             :                         } else {
     498             : #if OSL_DEBUG_LEVEL > 1
     499             :                             dumpWords (s, 1024);
     500             : #endif
     501             :                         }
     502           0 :                         break;
     503             :                     }
     504             :                 // linear gradient
     505             :                 case 4:
     506             :                     {
     507           0 :                         s >> additionalFlags >> wrapMode;
     508             : 
     509             :                         SAL_INFO("cppcanvas.emf", "EMF+\tlinear gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec);
     510             : 
     511           0 :                         s >> areaX >> areaY >> areaWidth >> areaHeight;
     512             : 
     513             :                         SAL_INFO("cppcanvas.emf", "EMF+\tarea: " << areaX << "," << areaY << " - " << areaWidth << "x" << areaHeight);
     514             : 
     515             :                         sal_uInt32 color;
     516             : 
     517           0 :                         s >> color;
     518           0 :                         solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
     519             :                         SAL_INFO("cppcanvas.emf", "EMF+\tfirst color: 0x" << std::hex << color << std::dec);
     520             : 
     521           0 :                         s >> color;
     522           0 :                         secondColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
     523             :                         SAL_INFO("cppcanvas.emf", "EMF+\tsecond color: 0x" << std::hex << color << std::dec);
     524             : 
     525             :                         // repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html
     526           0 :                         s >> color;
     527           0 :                         s >> color;
     528             : 
     529           0 :                         if (additionalFlags & 0x02) {
     530             :                             SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation");
     531           0 :                             s >> transformation;
     532           0 :                             hasTransformation = true;
     533             :                             SAL_INFO("cppcanvas.emf",
     534             :                                     "EMF+\tm11: "   << transformation.eM11 << " m12: " << transformation.eM12 <<
     535             :                                     "\nEMF+\tm21: " << transformation.eM21 << " m22: " << transformation.eM22 <<
     536             :                                     "\nEMF+\tdx: "  << transformation.eDx  << " dy: "  << transformation.eDy);
     537             :                         }
     538           0 :                         if (additionalFlags & 0x08) {
     539           0 :                             s >> blendPoints;
     540             :                             SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints);
     541           0 :                             if( blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
     542           0 :                                 blendPoints = SAL_MAX_INT32/(2*sizeof(float));
     543           0 :                             blendPositions = new float [2*blendPoints];
     544           0 :                             blendFactors = blendPositions + blendPoints;
     545           0 :                             for (int i=0; i < blendPoints; i ++) {
     546           0 :                                 s >> blendPositions [i];
     547             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions [i]);
     548             :                             }
     549           0 :                             for (int i=0; i < blendPoints; i ++) {
     550           0 :                                 s >> blendFactors [i];
     551             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors [i]);
     552             :                             }
     553             :                         }
     554             : 
     555           0 :                         if (additionalFlags & 0x04) {
     556           0 :                             s >> colorblendPoints;
     557             :                             SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints);
     558           0 :                             if( colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(float) )
     559           0 :                                 colorblendPoints = SAL_MAX_INT32/sizeof(float);
     560           0 :                             if( sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(::Color) )
     561           0 :                                 colorblendPoints = sal_uInt32(SAL_MAX_INT32)/sizeof(::Color);
     562           0 :                             colorblendPositions = new float [colorblendPoints];
     563           0 :                             colorblendColors = new ::Color [colorblendPoints];
     564           0 :                             for (int i=0; i < colorblendPoints; i ++) {
     565           0 :                                 s >> colorblendPositions [i];
     566             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions [i]);
     567             :                             }
     568           0 :                             for (int i=0; i < colorblendPoints; i ++) {
     569           0 :                                 s >> color;
     570           0 :                                 colorblendColors [i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
     571             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec);
     572             :                             }
     573             :                         }
     574             : 
     575           0 :                         break;
     576             :                     }
     577             :                 default:
     578             :                     SAL_INFO("cppcanvas.emf", "EMF+\tunhandled brush type: " << std::hex << type << std::dec);
     579             :                 }
     580           0 :             }
     581             :         };
     582             : 
     583           0 :         struct EMFPPen : public EMFPBrush
     584             :         {
     585             :             XForm transformation;
     586             :             float width;
     587             :             sal_Int32 startCap;
     588             :             sal_Int32 endCap;
     589             :             sal_Int32 lineJoin;
     590             :             float mitterLimit;
     591             :             sal_Int32 dashStyle;
     592             :             sal_Int32 dashCap;
     593             :             float dashOffset;
     594             :             sal_Int32 dashPatternLen;
     595             :             float *dashPattern;
     596             :             sal_Int32 alignment;
     597             :             sal_Int32 compoundArrayLen;
     598             :             float *compoundArray;
     599             :             sal_Int32 customStartCapLen;
     600             :             sal_uInt8 *customStartCap;
     601             :             sal_Int32 customEndCapLen;
     602             :             sal_uInt8 *customEndCap;
     603             : 
     604             :         public:
     605           0 :             EMFPPen () : EMFPBrush ()
     606             :             {
     607           0 :             }
     608             : 
     609           0 :             void SetStrokeAttributes (rendering::StrokeAttributes& rStrokeAttributes, ImplRenderer& rR, const OutDevState& rState)
     610             :             {
     611             : #if OSL_DEBUG_LEVEL > 1
     612             :                 if (width == 0.0) {
     613             :                     SAL_INFO ("cppcanvas.emf", "TODO: pen with zero width - using minimal which might not be correct\n");
     614             :                 }
     615             : #endif
     616           0 :                 rStrokeAttributes.StrokeWidth = (rState.mapModeTransform * rR.MapSize (width == 0.0 ? 0.05 : width, 0)).getX ();
     617           0 :             }
     618             : 
     619           0 :             void Read (SvStream& s, ImplRenderer& rR, sal_Int32, sal_Int32 )
     620             :             {
     621             :                 sal_uInt32 header, unknown, penFlags, unknown2;
     622             :                 int i;
     623             : 
     624           0 :                 s >> header >> unknown >> penFlags >> unknown2 >> width;
     625             : 
     626             :                 SAL_INFO("cppcanvas.emf", "EMF+\tpen");
     627             :                 SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " unknown: 0x" << unknown <<
     628             :                             " additional flags: 0x" << penFlags << " unknown: 0x" << unknown2 << " width: " << std::dec << width );
     629             : 
     630           0 :                 if (penFlags & 1)
     631           0 :                     s >> transformation;
     632             : 
     633           0 :                 if (penFlags & 2)
     634           0 :                     s >> startCap;
     635             :                 else
     636           0 :                     startCap = 0;
     637             : 
     638           0 :                 if (penFlags & 4)
     639           0 :                     s >> endCap;
     640             :                 else
     641           0 :                     endCap = 0;
     642             : 
     643           0 :                 if (penFlags & 8)
     644           0 :                     s >> lineJoin;
     645             :                 else
     646           0 :                     lineJoin = 0;
     647             : 
     648           0 :                 if (penFlags & 16)
     649           0 :                     s >> mitterLimit;
     650             :                 else
     651           0 :                     mitterLimit = 0;
     652             : 
     653           0 :                 if (penFlags & 32)
     654           0 :                     s >> dashStyle;
     655             :                 else
     656           0 :                     dashStyle = 0;
     657             : 
     658           0 :                 if (penFlags & 64)
     659           0 :                     s >> dashCap;
     660             :                 else
     661           0 :                     dashCap = 0;
     662             : 
     663           0 :                 if (penFlags & 128)
     664           0 :                     s >> dashOffset;
     665             :                 else
     666           0 :                     dashOffset = 0;
     667             : 
     668           0 :                 if (penFlags & 256) {
     669           0 :                     s >> dashPatternLen;
     670           0 :                     if( dashPatternLen<0 || sal_uInt32(dashPatternLen)>SAL_MAX_INT32/sizeof(float) )
     671           0 :                         dashPatternLen = SAL_MAX_INT32/sizeof(float);
     672           0 :                     dashPattern = new float [dashPatternLen];
     673           0 :                     for (i = 0; i < dashPatternLen; i++)
     674           0 :                         s >> dashPattern [i];
     675             :                 } else
     676           0 :                     dashPatternLen = 0;
     677             : 
     678           0 :                 if (penFlags & 512)
     679           0 :                     s >> alignment;
     680             :                 else
     681           0 :                     alignment = 0;
     682             : 
     683           0 :                 if (penFlags & 1024) {
     684           0 :                     s >> compoundArrayLen;
     685           0 :                     if( compoundArrayLen<0 || sal_uInt32(compoundArrayLen)>SAL_MAX_INT32/sizeof(float) )
     686           0 :                         compoundArrayLen = SAL_MAX_INT32/sizeof(float);
     687           0 :                     compoundArray = new float [compoundArrayLen];
     688           0 :                     for (i = 0; i < compoundArrayLen; i++)
     689           0 :                         s >> compoundArray [i];
     690             :                 } else
     691           0 :                     compoundArrayLen = 0;
     692             : 
     693           0 :                 if (penFlags & 2048) {
     694           0 :                     s >> customStartCapLen;
     695           0 :                     if( customStartCapLen<0 )
     696           0 :                         customStartCapLen=0;
     697           0 :                     customStartCap = new sal_uInt8 [customStartCapLen];
     698           0 :                     for (i = 0; i < customStartCapLen; i++)
     699           0 :                         s >> customStartCap [i];
     700             :                 } else
     701           0 :                     customStartCapLen = 0;
     702             : 
     703           0 :                 if (penFlags & 4096) {
     704           0 :                     s >> customEndCapLen;
     705           0 :                     if( customEndCapLen<0 )
     706           0 :                         customEndCapLen=0;
     707           0 :                     customEndCap = new sal_uInt8 [customEndCapLen];
     708           0 :                     for (i = 0; i < customEndCapLen; i++)
     709           0 :                         s >> customEndCap [i];
     710             :                 } else
     711           0 :                     customEndCapLen = 0;
     712             : 
     713           0 :                 EMFPBrush::Read (s, rR);
     714           0 :             }
     715             :         };
     716             : 
     717           0 :         struct EMFPImage : public EMFPObject
     718             :         {
     719             :             sal_uInt32 type;
     720             :             sal_Int32 width;
     721             :             sal_Int32 height;
     722             :             sal_Int32 stride;
     723             :             sal_Int32 pixelFormat;
     724             :             Graphic graphic;
     725             : 
     726             : 
     727           0 :             void Read (SvMemoryStream &s, sal_uInt32 dataSize, sal_Bool bUseWholeStream)
     728             :             {
     729             :                 sal_uInt32 header, unknown;
     730             : 
     731           0 :                 s >> header >> type;
     732             : 
     733             :                 SAL_INFO("cppcanvas.emf", "EMF+\timage\nEMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec );
     734             : 
     735           0 :                 if (type == 1) { // bitmap
     736           0 :                     s >> width >> height >> stride >> pixelFormat >> unknown;
     737             :                     SAL_INFO("cppcanvas.emf", "EMF+\tbitmap width: " << width << " height: " << height << " stride: " << "pixelFormat: 0x" << std::hex << pixelFormat << std::dec);
     738           0 :                     if (width == 0) { // non native formats
     739           0 :                         GraphicFilter filter;
     740             : 
     741           0 :                         filter.ImportGraphic (graphic, String (), s);
     742           0 :                         SAL_INFO("cppcanvas.emf", "EMF+\tbitmap width: "  << graphic.GetBitmap().GetSizePixel().Width() << " height: " << graphic.GetBitmap().GetSizePixel().Height());
     743             :                     }
     744             : 
     745           0 :                 } else if (type == 2) {
     746             :                     sal_Int32 mfType, mfSize;
     747             : 
     748           0 :                     s >> mfType >> mfSize;
     749             :                     SAL_INFO("cppcanvas.emf", "EMF+\tmetafile type: " << mfType << " dataSize: " << mfSize << " real size calculated from record dataSize: " << dataSize - 16);
     750             : 
     751           0 :                     GraphicFilter filter;
     752             :                     // workaround buggy metafiles, which have wrong mfSize set (n#705956 for example)
     753           0 :                     SvMemoryStream mfStream (((char *)s.GetData()) + s.Tell(), bUseWholeStream ? s.remainingSize() : dataSize - 16, STREAM_READ);
     754             : 
     755           0 :                     filter.ImportGraphic (graphic, String (), mfStream);
     756             : 
     757             :                     // debug code - write the stream to debug file /tmp/emf-stream.emf
     758             : #if OSL_DEBUG_LEVEL > 1
     759             :                         mfStream.Seek(0);
     760             :                         static sal_Int32 emfp_debug_stream_number = 0;
     761             :                         OUString emfp_debug_filename("/tmp/emf-embedded-stream");
     762             :                         emfp_debug_filename += OUString::valueOf(emfp_debug_stream_number++);
     763             :                         emfp_debug_filename += OUString(".emf");
     764             : 
     765             :                         SvFileStream file( emfp_debug_filename, STREAM_WRITE | STREAM_TRUNC );
     766             : 
     767             :                         mfStream >> file;
     768             :                         file.Flush();
     769             :                         file.Close();
     770             : #endif
     771             :                 }
     772           0 :             }
     773             :         };
     774             : 
     775           0 :         struct EMFPFont : public EMFPObject
     776             :         {
     777             :             sal_uInt32 version;
     778             :             float emSize;
     779             :             sal_uInt32 sizeUnit;
     780             :             sal_Int32 fontFlags;
     781             :             OUString family;
     782             : 
     783           0 :             void Read (SvMemoryStream &s)
     784             :             {
     785             :                 sal_uInt32 header;
     786             :                 sal_uInt32 reserved;
     787             :                 sal_uInt32 length;
     788             : 
     789           0 :                 s >> header >> emSize >> sizeUnit >> fontFlags >> reserved >> length;
     790             : 
     791             :                 OSL_ASSERT( ( header >> 12 ) == 0xdbc01 );
     792             : 
     793             :                 SAL_INFO("cppcanvas.emf", "EMF+\tfont\n"
     794             :                            << "EMF+\theader: 0x" << std::hex << (header >> 12) << " version: 0x" << (header & 0x1fff) << " size: " << std::dec << emSize << " unit: 0x" << std::hex << sizeUnit << std::dec);
     795             :                 SAL_INFO("cppcanvas.emf", "EMF+\tflags: 0x" << std::hex << fontFlags << " reserved: 0x" << reserved << " length: 0x" << std::hex << length << std::dec);
     796             : 
     797           0 :                 if( length > 0 && length < 0x4000 ) {
     798           0 :                     sal_Unicode *chars = (sal_Unicode *) alloca( sizeof( sal_Unicode ) * length );
     799             : 
     800           0 :                     for( sal_uInt32 i = 0; i < length; i++ )
     801           0 :                         s >> chars[ i ];
     802             : 
     803           0 :                     family = OUString( chars, length );
     804             :                     SAL_INFO("cppcanvas.emf", "EMF+\tfamily: " << OUStringToOString( family, RTL_TEXTENCODING_UTF8).getStr()); // TODO: can we just use family?
     805             :                 }
     806           0 :             }
     807             :         };
     808             : 
     809           0 :         void ImplRenderer::ReadRectangle (SvStream& s, float& x, float& y, float &width, float& height, bool bCompressed)
     810             :         {
     811           0 :             if (bCompressed) {
     812             :                 sal_Int16 ix, iy, iw, ih;
     813             : 
     814           0 :                 s >> ix >> iy >> iw >> ih;
     815             : 
     816           0 :                 x = ix;
     817           0 :                 y = iy;
     818           0 :                 width = iw;
     819           0 :                 height = ih;
     820             :             } else
     821           0 :                 s >> x >> y >> width >> height;
     822           0 :         }
     823             : 
     824           0 :         void ImplRenderer::ReadPoint (SvStream& s, float& x, float& y, sal_uInt32 flags)
     825             :         {
     826           0 :             if (flags & 0x4000) {
     827             :                 sal_Int16 ix, iy;
     828             : 
     829           0 :                 s >> ix >> iy;
     830             : 
     831           0 :                 x = ix;
     832           0 :                 y = iy;
     833             :             } else
     834           0 :                 s >> x >> y;
     835           0 :         }
     836             : 
     837           0 :         void ImplRenderer::MapToDevice (double& x, double& y)
     838             :         {
     839             :             // TODO: other units
     840           0 :             x = 100*nMmX*x/nPixX;
     841           0 :             y = 100*nMmY*y/nPixY;
     842           0 :         }
     843             : 
     844           0 :         ::basegfx::B2DPoint ImplRenderer::Map (double ix, double iy)
     845             :         {
     846             :             double x, y;
     847             : 
     848           0 :             x = ix*aWorldTransform.eM11 + iy*aWorldTransform.eM21 + aWorldTransform.eDx;
     849           0 :             y = ix*aWorldTransform.eM12 + iy*aWorldTransform.eM22 + aWorldTransform.eDy;
     850             : 
     851           0 :             MapToDevice (x, y);
     852             : 
     853           0 :             x -= nFrameLeft;
     854           0 :             y -= nFrameTop;
     855             : 
     856           0 :             return ::basegfx::B2DPoint (x, y);
     857             :         }
     858             : 
     859           0 :         ::basegfx::B2DSize ImplRenderer::MapSize (double iwidth, double iheight)
     860             :         {
     861             :             double w, h;
     862             : 
     863           0 :             w = iwidth*aWorldTransform.eM11 + iheight*aWorldTransform.eM21;
     864           0 :             h = iwidth*aWorldTransform.eM12 + iheight*aWorldTransform.eM22;
     865             : 
     866           0 :             MapToDevice (w, h);
     867             : 
     868           0 :             return ::basegfx::B2DSize (w, h);
     869             :         }
     870             : 
     871             : #define COLOR(x) \
     872             :     ::vcl::unotools::colorToDoubleSequence( ::Color (0xff - (x >> 24), \
     873             :                              (x >> 16) & 0xff, \
     874             :                              (x >> 8) & 0xff, \
     875             :                              x & 0xff), \
     876             :                         rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace());
     877             : 
     878           0 :         void ImplRenderer::EMFPPlusFillPolygon (::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms,
     879             :                                                 OutDevState& rState, const CanvasSharedPtr& rCanvas, bool isColor, sal_uInt32 brushIndexOrColor)
     880             :         {
     881           0 :             ::basegfx::B2DPolyPolygon localPolygon (polygon);
     882             : 
     883             :             SAL_INFO("cppcanvas.emf", "EMF+\tfill polygon");
     884             : 
     885           0 :             localPolygon.transform( rState.mapModeTransform );
     886             : 
     887           0 :             ActionSharedPtr pPolyAction;
     888             : 
     889           0 :             if (isColor) {
     890             :                 SAL_INFO("cppcanvas.emf", "EMF+\t\tcolor fill:0x" << std::hex << brushIndexOrColor << std::dec);
     891           0 :                 rState.isFillColorSet = true;
     892           0 :                 rState.isLineColorSet = false;
     893             : 
     894           0 :                 rState.fillColor = COLOR(brushIndexOrColor);
     895             : 
     896           0 :                 pPolyAction = ActionSharedPtr ( internal::PolyPolyActionFactory::createPolyPolyAction( localPolygon, rParms.mrCanvas, rState ) );
     897             : 
     898             :             } else {
     899           0 :                 rState.isFillColorSet = true;
     900             :                 // extract UseBrush
     901           0 :                 EMFPBrush* brush = (EMFPBrush*) aObjects [brushIndexOrColor & 0xff];
     902             :                 SAL_INFO("cppcanvas.emf", "EMF+\tbrush fill slot: " << brushIndexOrColor << " (type: " << brush->GetType () << ")");
     903             : 
     904             :                 // give up in case something wrong happened
     905           0 :                 if( !brush )
     906           0 :                     return;
     907             : 
     908           0 :                 rState.isFillColorSet = false;
     909           0 :                 rState.isLineColorSet = false;
     910             : 
     911           0 :                 if (brush->type == 3 || brush->type == 4) {
     912             : 
     913           0 :                     if (brush->type == 3 && !(brush->additionalFlags & 0x1))
     914           0 :                         return;  // we are unable to parse these brushes yet
     915             : 
     916           0 :                     ::basegfx::B2DHomMatrix aTextureTransformation;
     917           0 :                     ::basegfx::B2DHomMatrix aWorldTransformation;
     918           0 :                     rendering::Texture aTexture;
     919             : 
     920           0 :                     aWorldTransformation.set (0, 0, aWorldTransform.eM11);
     921           0 :                     aWorldTransformation.set (0, 1, aWorldTransform.eM21);
     922           0 :                     aWorldTransformation.set (0, 2, aWorldTransform.eDx);
     923           0 :                     aWorldTransformation.set (1, 0, aWorldTransform.eM12);
     924           0 :                     aWorldTransformation.set (1, 1, aWorldTransform.eM22);
     925           0 :                     aWorldTransformation.set (1, 2, aWorldTransform.eDy);
     926             : 
     927           0 :                     if (brush->type == 4) {
     928           0 :                         aTextureTransformation.scale (brush->areaWidth, brush->areaHeight);
     929           0 :                         aTextureTransformation.translate (brush->areaX, brush->areaY);
     930             :                     } else {
     931           0 :                         aTextureTransformation.translate (-0.5, -0.5);
     932           0 :                         aTextureTransformation.scale (brush->areaWidth, brush->areaHeight);
     933           0 :                         aTextureTransformation.translate (brush->areaX,brush->areaY);
     934             :                     }
     935             : 
     936           0 :                     if (brush->hasTransformation) {
     937           0 :                         ::basegfx::B2DHomMatrix aTransformation;
     938             : 
     939           0 :                         aTransformation.set (0, 0, brush->transformation.eM11);
     940           0 :                         aTransformation.set (0, 1, brush->transformation.eM21);
     941           0 :                         aTransformation.set (0, 2, brush->transformation.eDx);
     942           0 :                         aTransformation.set (1, 0, brush->transformation.eM12);
     943           0 :                         aTransformation.set (1, 1, brush->transformation.eM22);
     944           0 :                         aTransformation.set (1, 2, brush->transformation.eDy);
     945             : 
     946           0 :                         aTextureTransformation *= aTransformation;
     947             :                     }
     948             : 
     949           0 :                     aTextureTransformation *= aWorldTransformation;
     950           0 :                     aTextureTransformation.scale (100.0*nMmX/nPixX, 100.0*nMmY/nPixY);
     951           0 :                     aTextureTransformation.translate (-nFrameLeft, -nFrameTop);
     952           0 :                     aTextureTransformation *= rState.mapModeTransform;
     953             : 
     954           0 :                     aTexture.RepeatModeX = rendering::TexturingMode::CLAMP;
     955           0 :                     aTexture.RepeatModeY = rendering::TexturingMode::CLAMP;
     956           0 :                     aTexture.Alpha = 1.0;
     957             : 
     958           0 :                     basegfx::ODFGradientInfo aGradInfo;
     959           0 :                     OUString aGradientService;
     960             : 
     961             :                     const uno::Sequence< double > aStartColor(
     962             :                             ::vcl::unotools::colorToDoubleSequence( brush->solidColor,
     963           0 :                                 rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() ) );
     964             :                     const uno::Sequence< double > aEndColor(
     965             :                             ::vcl::unotools::colorToDoubleSequence( brush->secondColor,
     966           0 :                                 rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() ) );
     967           0 :                     uno::Sequence< uno::Sequence < double > > aColors (2);
     968           0 :                     uno::Sequence< double > aStops (2);
     969             : 
     970           0 :                     if (brush->blendPositions) {
     971             :                         SAL_INFO("cppcanvas.emf", "EMF+\t\tuse blend");
     972           0 :                         aColors.realloc (brush->blendPoints);
     973           0 :                         aStops.realloc (brush->blendPoints);
     974           0 :                         int length = aStartColor.getLength ();
     975           0 :                         uno::Sequence< double > aColor (length);
     976             : 
     977             :                         OSL_ASSERT (length == aEndColor.getLength());
     978             : 
     979           0 :                         for (int i = 0; i < brush->blendPoints; i++) {
     980           0 :                             aStops[i] = brush->blendPositions [i];
     981             : 
     982           0 :                             for (int j = 0; j < length; j++) {
     983           0 :                                 if (brush->type == 4) {
     984           0 :                                     aColor [j] = aStartColor [j]*(1 - brush->blendFactors[i]) + aEndColor [j]*brush->blendFactors[i];
     985             :                                 } else
     986           0 :                                     aColor [j] = aStartColor [j]*brush->blendFactors[i] + aEndColor [j]*(1 - brush->blendFactors[i]);
     987             :                             }
     988             : 
     989           0 :                             aColors[i] = aColor;
     990           0 :                         }
     991           0 :                     } else if (brush->colorblendPositions) {
     992             :                         SAL_INFO("cppcanvas.emf", "EMF+\t\tuse color blend");
     993           0 :                         aColors.realloc (brush->colorblendPoints);
     994           0 :                         aStops.realloc (brush->colorblendPoints);
     995             : 
     996           0 :                         for (int i = 0; i < brush->colorblendPoints; i++) {
     997           0 :                             aStops[i] = brush->colorblendPositions [i];
     998           0 :                             aColors[(brush->type == 4) ? i : brush->colorblendPoints - 1 - i] = ::vcl::unotools::colorToDoubleSequence( brush->colorblendColors [i],
     999           0 :                                     rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
    1000             :                         }
    1001             :                     } else {
    1002           0 :                         aStops[0] = 0.0;
    1003           0 :                         aStops[1] = 1.0;
    1004             : 
    1005           0 :                         if (brush->type == 4) {
    1006           0 :                             aColors[0] = aStartColor;
    1007           0 :                             aColors[1] = aEndColor;
    1008             :                         } else {
    1009           0 :                             aColors[1] = aStartColor;
    1010           0 :                             aColors[0] = aEndColor;
    1011             :                         }
    1012             :                     }
    1013             : 
    1014             :                     SAL_INFO("cppcanvas.emf", "EMF+\t\tset gradient");
    1015           0 :                     basegfx::B2DRange aBoundsRectangle (0, 0, 1, 1);
    1016           0 :                     if (brush->type == 4) {
    1017           0 :                         aGradientService = "LinearGradient";
    1018           0 :                         aGradInfo = basegfx::tools::createLinearODFGradientInfo(
    1019             :                                 aBoundsRectangle,
    1020           0 :                                 aStops.getLength(),
    1021             :                                 0,
    1022           0 :                                 0);
    1023             : 
    1024             :                     } else {
    1025           0 :                         aGradientService = "EllipticalGradient";
    1026           0 :                         aGradInfo = basegfx::tools::createEllipticalODFGradientInfo(
    1027             :                                 aBoundsRectangle,
    1028             :                                 ::basegfx::B2DVector( 0, 0 ),
    1029           0 :                                 aStops.getLength(),
    1030             :                                 0,
    1031           0 :                                 0);
    1032             :                     }
    1033             : 
    1034             :                     uno::Reference< lang::XMultiServiceFactory > xFactory(
    1035           0 :                             rParms.mrCanvas->getUNOCanvas()->getDevice()->getParametricPolyPolygonFactory() );
    1036             : 
    1037           0 :                     if( xFactory.is() ) {
    1038           0 :                         uno::Sequence<uno::Any> args( 3 );
    1039           0 :                         beans::PropertyValue aProp;
    1040           0 :                         aProp.Name = "Colors";
    1041           0 :                         aProp.Value <<= aColors;
    1042           0 :                         args[0] <<= aProp;
    1043           0 :                         aProp.Name = "Stops";
    1044           0 :                         aProp.Value <<= aStops;
    1045           0 :                         args[1] <<= aProp;
    1046           0 :                         aProp.Name = "AspectRatio";
    1047           0 :                         aProp.Value <<= static_cast<sal_Int32>(1);
    1048           0 :                         args[2] <<= aProp;
    1049             : 
    1050             :                         aTexture.Gradient.set(
    1051           0 :                                 xFactory->createInstanceWithArguments( aGradientService,
    1052           0 :                                     args ),
    1053           0 :                                 uno::UNO_QUERY);
    1054             :                     }
    1055             : 
    1056             :                     ::basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform,
    1057           0 :                             aTextureTransformation );
    1058             : 
    1059           0 :                     if( aTexture.Gradient.is() )
    1060           0 :                         pPolyAction =
    1061             :                             ActionSharedPtr ( internal::PolyPolyActionFactory::createPolyPolyAction( localPolygon,
    1062             :                                         rParms.mrCanvas,
    1063             :                                         rState,
    1064           0 :                                         aTexture ) );
    1065             :                 }
    1066             :             }
    1067             : 
    1068           0 :             if( pPolyAction )
    1069             :             {
    1070             :                 SAL_INFO("cppcanvas.emf", "EMF+\t\tadd poly action");
    1071             : 
    1072             :                 maActions.push_back(
    1073             :                     MtfAction(
    1074             :                         pPolyAction,
    1075           0 :                         rParms.mrCurrActionIndex ) );
    1076             : 
    1077           0 :                 rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
    1078           0 :             }
    1079             :         }
    1080             : 
    1081           0 :         void ImplRenderer::EMFPPlusDrawPolygon (::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms,
    1082             :                                                 OutDevState& rState, const CanvasSharedPtr& rCanvas, sal_uInt32 penIndex)
    1083             :         {
    1084           0 :             EMFPPen* pen = (EMFPPen*) aObjects [penIndex & 0xff];
    1085             : 
    1086             :             SAL_WARN_IF( !pen, "cppcanvas.emf", "emf+ missing pen" );
    1087             : 
    1088           0 :             if (pen)
    1089             :             {
    1090           0 :                 rState.isFillColorSet = false;
    1091           0 :                 rState.isLineColorSet = true;
    1092           0 :                 rState.lineColor = ::vcl::unotools::colorToDoubleSequence (pen->GetColor (),
    1093           0 :                                                                            rCanvas->getUNOCanvas ()->getDevice()->getDeviceColorSpace());
    1094             : 
    1095           0 :                 polygon.transform( rState.mapModeTransform );
    1096           0 :                 rendering::StrokeAttributes aStrokeAttributes;
    1097             : 
    1098           0 :                 pen->SetStrokeAttributes (aStrokeAttributes, *this, rState);
    1099             : 
    1100             :                 ActionSharedPtr pPolyAction(
    1101             :                                             internal::PolyPolyActionFactory::createPolyPolyAction(
    1102           0 :                                                                                                   polygon, rParms.mrCanvas, rState, aStrokeAttributes ) );
    1103             : 
    1104           0 :                 if( pPolyAction )
    1105             :                 {
    1106             :                     maActions.push_back(
    1107             :                                         MtfAction(
    1108             :                                                   pPolyAction,
    1109           0 :                                                   rParms.mrCurrActionIndex ) );
    1110             : 
    1111           0 :                     rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
    1112           0 :                 }
    1113             :             }
    1114           0 :         }
    1115             : 
    1116           0 :         void ImplRenderer::processObjectRecord(SvMemoryStream& rObjectStream, sal_uInt16 flags, sal_uInt32 dataSize, sal_Bool bUseWholeStream)
    1117             :         {
    1118             :             sal_uInt32 index;
    1119             : 
    1120             :             SAL_INFO("cppcanvas.emf", "EMF+ Object slot: " << (flags & 0xff) << " flags: " << (flags & 0xff00));
    1121             : 
    1122           0 :             index = flags & 0xff;
    1123           0 :             if (aObjects [index] != NULL) {
    1124           0 :                 delete aObjects [index];
    1125           0 :                 aObjects [index] = NULL;
    1126             :             }
    1127             : 
    1128           0 :             switch (flags & 0x7f00) {
    1129             :             case EmfPlusObjectTypeBrush:
    1130             :                 {
    1131             :                     EMFPBrush *brush;
    1132           0 :                     aObjects [index] = brush = new EMFPBrush ();
    1133           0 :                     brush->Read (rObjectStream, *this);
    1134             : 
    1135           0 :                     break;
    1136             :                 }
    1137             :             case EmfPlusObjectTypePen:
    1138             :                 {
    1139             :                     EMFPPen *pen;
    1140           0 :                     aObjects [index] = pen = new EMFPPen ();
    1141           0 :                     pen->Read (rObjectStream, *this, nHDPI, nVDPI);
    1142             : 
    1143           0 :                     break;
    1144             :                 }
    1145             :             case EmfPlusObjectTypePath:
    1146             :                 sal_uInt32 header, pathFlags;
    1147             :                 sal_Int32 points;
    1148             : 
    1149           0 :                 rObjectStream >> header >> points >> pathFlags;
    1150             : 
    1151             :                 SAL_INFO("cppcanvas.emf", "EMF+\tpath");
    1152             :                 SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " points: " << std::dec << points << " additional flags: 0x" << std::hex << pathFlags << std::dec);
    1153             : 
    1154             :                 EMFPPath *path;
    1155           0 :                 aObjects [index] = path = new EMFPPath (points);
    1156           0 :                 path->Read (rObjectStream, pathFlags, *this);
    1157             : 
    1158           0 :                 break;
    1159             :             case EmfPlusObjectTypeRegion: {
    1160             :                 EMFPRegion *region;
    1161             : 
    1162           0 :                 aObjects [index] = region = new EMFPRegion ();
    1163           0 :                 region->Read (rObjectStream);
    1164             : 
    1165           0 :                 break;
    1166             :             }
    1167             :             case EmfPlusObjectTypeImage:
    1168             :                 {
    1169             :                     EMFPImage *image;
    1170           0 :                     aObjects [index] = image = new EMFPImage ();
    1171           0 :                     image->Read (rObjectStream, dataSize, bUseWholeStream);
    1172             : 
    1173           0 :                     break;
    1174             :                 }
    1175             :             case EmfPlusObjectTypeFont:
    1176             :                 {
    1177             :                     EMFPFont *font;
    1178           0 :                     aObjects [index] = font = new EMFPFont ();
    1179           0 :                     font->Read (rObjectStream);
    1180             : 
    1181           0 :                     break;
    1182             :                 }
    1183             :             default:
    1184             :                 SAL_INFO("cppcanvas.emf", "EMF+\tObject unhandled flags: 0x" << std::hex << (flags & 0xff00) << std::dec);
    1185           0 :                 break;
    1186             :             }
    1187           0 :         }
    1188             : 
    1189           0 :         double ImplRenderer::setFont (sal_uInt8 objectId, const ActionFactoryParameters& rParms, OutDevState& rState)
    1190             :         {
    1191           0 :             EMFPFont *font = (EMFPFont*) aObjects[ objectId ];
    1192             : 
    1193           0 :             rendering::FontRequest aFontRequest;
    1194           0 :             aFontRequest.FontDescription.FamilyName = font->family;
    1195           0 :             double cellSize = font->emSize;
    1196           0 :             aFontRequest.CellSize = (rState.mapModeTransform*MapSize( cellSize, 0 )).getX();
    1197           0 :             rState.xFont = rParms.mrCanvas->getUNOCanvas()->createFont( aFontRequest,
    1198             :                                                uno::Sequence< beans::PropertyValue >(),
    1199           0 :                                                geometry::Matrix2D() );
    1200             : 
    1201           0 :             return cellSize;
    1202             :         }
    1203             : 
    1204           0 :         void ImplRenderer::GraphicStatePush(GraphicStateMap& map, sal_Int32 index, OutDevState& rState)
    1205             :         {
    1206           0 :             GraphicStateMap::iterator iter = map.find( index );
    1207             : 
    1208           0 :             if ( iter != map.end() )
    1209             :             {
    1210           0 :                 EmfPlusGraphicState state = iter->second;
    1211           0 :                 map.erase( iter );
    1212             : 
    1213           0 :                 SAL_INFO("cppcanvas.emf", "stack index: " << index << " found and erased");
    1214             :             }
    1215             : 
    1216           0 :             EmfPlusGraphicState state;
    1217             : 
    1218           0 :             state.aWorldTransform = aWorldTransform;
    1219           0 :             state.aDevState = rState;
    1220             : 
    1221           0 :             map[ index ] = state;
    1222           0 :         }
    1223             : 
    1224           0 :         void ImplRenderer::GraphicStatePop(GraphicStateMap& map, sal_Int32 index, OutDevState& rState)
    1225             :         {
    1226           0 :             GraphicStateMap::iterator iter = map.find( index );
    1227             : 
    1228           0 :             if ( iter != map.end() )
    1229             :             {
    1230             :                 SAL_INFO("cppcanvas.emf", "stack index: " << index << " found");
    1231             : 
    1232           0 :                 EmfPlusGraphicState state = iter->second;
    1233             : 
    1234           0 :                 aWorldTransform = state.aWorldTransform;
    1235           0 :                 rState.clip = state.aDevState.clip;
    1236           0 :                 rState.clipRect = state.aDevState.clipRect;
    1237           0 :                 rState.xClipPoly = state.aDevState.xClipPoly;
    1238             :             }
    1239           0 :         }
    1240             : 
    1241           0 :         void ImplRenderer::processEMFPlus( MetaCommentAction* pAct, const ActionFactoryParameters& rFactoryParms,
    1242             :                                            OutDevState& rState, const CanvasSharedPtr& rCanvas )
    1243             :         {
    1244           0 :             sal_uInt32 length = pAct->GetDataSize ();
    1245           0 :             SvMemoryStream rMF ((void*) pAct->GetData (), length, STREAM_READ);
    1246             : 
    1247             : #if OSL_DEBUG_LEVEL > 2
    1248             :             SAL_INFO("cppcanvas.emf", "EMF+\tDump of EMF+ record");
    1249             :             dumpWords(rMF, length);
    1250             : #endif
    1251           0 :             length -= 4;
    1252             : 
    1253           0 :             while (length > 0) {
    1254             :                 sal_uInt16 type, flags;
    1255             :                 sal_uInt32 size, dataSize;
    1256             :                 sal_uInt32 next;
    1257             : 
    1258           0 :                 rMF >> type >> flags >> size >> dataSize;
    1259             : 
    1260           0 :                 next = rMF.Tell() + ( size - 12 );
    1261             : 
    1262           0 :                 if (size < 12) {
    1263             :                     SAL_INFO("cppcanvas.emf", "Size field is less than 12 bytes");
    1264             :                 }
    1265             : 
    1266             :                 SAL_INFO("cppcanvas.emf", "EMF+ record size: " << size << " type: " << type << " flags: " << flags << " data size: " << dataSize);
    1267             : 
    1268           0 :                 if (type == EmfPlusRecordTypeObject && ((mbMultipart && (flags & 0x7fff) == (mMFlags & 0x7fff)) || (flags & 0x8000))) {
    1269           0 :                     if (!mbMultipart) {
    1270           0 :                         mbMultipart = true;
    1271           0 :                         mMFlags = flags;
    1272           0 :                         mMStream.Seek(0);
    1273             :                     }
    1274             : 
    1275             :                     // 1st 4 bytes are unknown
    1276           0 :                     mMStream.Write (((const char *)rMF.GetData()) + rMF.Tell() + 4, dataSize - 4);
    1277           0 :                     SAL_INFO("cppcanvas.emf", "EMF+ read next object part size: " << size << " type: " << type << " flags: " << flags << " data size: " << dataSize);
    1278             :                 } else {
    1279           0 :                     if (mbMultipart) {
    1280             :                         SAL_INFO("cppcanvas.emf", "EMF+ multipart record flags: " << mMFlags);
    1281           0 :                         mMStream.Seek (0);
    1282           0 :                         processObjectRecord (mMStream, mMFlags, dataSize, sal_True);
    1283             :                     }
    1284           0 :                     mbMultipart = false;
    1285             :                 }
    1286             : 
    1287           0 :                 if (type != EmfPlusRecordTypeObject || !(flags & 0x8000))
    1288             :                 {
    1289           0 :                     switch (type) {
    1290             :                     case EmfPlusRecordTypeHeader:
    1291             :                         sal_uInt32 header, version;
    1292             : 
    1293           0 :                         rMF >> header >> version >> nHDPI >> nVDPI;
    1294             : 
    1295             :                         SAL_INFO("cppcanvas.emf", "EMF+ Header");
    1296             :                         SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " version: " << std::dec << version << " horizontal DPI: " << nHDPI << " vertical DPI: " << nVDPI << " dual: " << (flags & 1));
    1297             : 
    1298           0 :                         break;
    1299             :                     case EmfPlusRecordTypeEndOfFile:
    1300             :                         SAL_INFO("cppcanvas.emf", "EMF+ EndOfFile");
    1301           0 :                         break;
    1302             :                     case EmfPlusRecordTypeGetDC:
    1303             :                         SAL_INFO("cppcanvas.emf", "EMF+ GetDC");
    1304             :                         SAL_INFO("cppcanvas.emf", "EMF+\talready used in svtools wmf/emf filter parser");
    1305           0 :                         break;
    1306             :                     case EmfPlusRecordTypeObject:
    1307           0 :                         processObjectRecord (rMF, flags, dataSize);
    1308           0 :                         break;
    1309             :                     case EmfPlusRecordTypeFillPie:
    1310             :                         {
    1311             :                             sal_uInt32 brushIndexOrColor;
    1312             :                             float startAngle, sweepAngle;
    1313             : 
    1314           0 :                             rMF >> brushIndexOrColor >> startAngle >> sweepAngle;
    1315             : 
    1316             :                             SAL_INFO("cppcanvas.emf", "EMF+ FillPie colorOrIndex: " << brushIndexOrColor << " startAngle: " << startAngle << " sweepAngle: " << sweepAngle);
    1317             : 
    1318             :                             float dx, dy, dw, dh;
    1319             : 
    1320           0 :                             ReadRectangle (rMF, dx, dy, dw, dh, flags & 0x4000);
    1321             : 
    1322             :                             SAL_INFO("cppcanvas.emf", "EMF+ RectData: " << dx << "," << dy << " " << dw << "x" << dh);
    1323             : 
    1324           0 :                             startAngle = 2*M_PI*startAngle/360;
    1325           0 :                             sweepAngle = 2*M_PI*sweepAngle/360;
    1326             : 
    1327           0 :                             B2DPoint mappedCenter (Map (dx + dw/2, dy + dh/2));
    1328           0 :                             B2DSize mappedSize( MapSize (dw/2, dh/2));
    1329             : 
    1330           0 :                             float endAngle = startAngle + sweepAngle;
    1331           0 :                             startAngle = fmodf(startAngle, static_cast<float>(M_PI*2));
    1332           0 :                             if (startAngle < 0)
    1333           0 :                                 startAngle += static_cast<float>(M_PI*2);
    1334           0 :                             endAngle = fmodf(endAngle, static_cast<float>(M_PI*2));
    1335           0 :                             if (endAngle < 0)
    1336           0 :                                 endAngle += static_cast<float>(M_PI*2);
    1337             : 
    1338           0 :                             if (sweepAngle < 0)
    1339           0 :                                 std::swap (endAngle, startAngle);
    1340             : 
    1341             :                             SAL_INFO("cppcanvas.emf", "EMF+ adjusted angles: start " <<
    1342             :                                      (360.0*startAngle/M_PI) << ", end: " << (360.0*endAngle/M_PI));
    1343             : 
    1344           0 :                             B2DPolygon polygon = tools::createPolygonFromEllipseSegment (mappedCenter, mappedSize.getX (), mappedSize.getY (), startAngle, endAngle);
    1345           0 :                             polygon.append (mappedCenter);
    1346           0 :                             polygon.setClosed (true);
    1347             : 
    1348           0 :                             B2DPolyPolygon polyPolygon (polygon);
    1349           0 :                             EMFPPlusFillPolygon (polyPolygon, rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
    1350             :                         }
    1351           0 :                         break;
    1352             :                     case EmfPlusRecordTypeFillPath:
    1353             :                         {
    1354           0 :                             sal_uInt32 index = flags & 0xff;
    1355             :                             sal_uInt32 brushIndexOrColor;
    1356             : 
    1357           0 :                             rMF >> brushIndexOrColor;
    1358             : 
    1359             :                             SAL_INFO("cppcanvas.emf", "EMF+ FillPath slot: " << index);
    1360             : 
    1361           0 :                             EMFPPlusFillPolygon (((EMFPPath*) aObjects [index])->GetPolygon (*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
    1362             :                         }
    1363           0 :                         break;
    1364             :                     case EmfPlusRecordTypeDrawEllipse:
    1365             :                     case EmfPlusRecordTypeFillEllipse:
    1366             :                         {
    1367             :                             // Intentionally very bogus initial value to avoid MSVC complaining about potentially uninitialized local
    1368             :                             // variable. As long as the code stays as intended, this variable will be assigned a (real) value in the case
    1369             :                             // when it is later used.
    1370           0 :                             sal_uInt32 brushIndexOrColor = 1234567;
    1371             : 
    1372           0 :                             if ( type == EmfPlusRecordTypeFillEllipse )
    1373           0 :                                 rMF >> brushIndexOrColor;
    1374             : 
    1375             :                             SAL_INFO("cppcanvas.emf", "EMF+ " << (type == EmfPlusRecordTypeFillEllipse ? "Fill" : "Draw") << "Ellipse slot: " << (flags & 0xff));
    1376             : 
    1377             :                             float dx, dy, dw, dh;
    1378             : 
    1379           0 :                             ReadRectangle (rMF, dx, dy, dw, dh, flags & 0x4000);
    1380             : 
    1381             :                             SAL_INFO("cppcanvas.emf", "EMF+ RectData: " << dx << "," << dy << " " << dw << "x" << dh);
    1382             : 
    1383           0 :                             B2DPoint mappedCenter (Map (dx + dw/2, dy + dh/2));
    1384           0 :                             B2DSize mappedSize( MapSize (dw/2, dh/2));
    1385             : 
    1386           0 :                             ::basegfx::B2DPolyPolygon polyPolygon( ::basegfx::B2DPolygon( ::basegfx::tools::createPolygonFromEllipse( mappedCenter, mappedSize.getX (), mappedSize.getY () ) ) );
    1387             : 
    1388           0 :                             if ( type == EmfPlusRecordTypeFillEllipse )
    1389             :                                 EMFPPlusFillPolygon( polyPolygon,
    1390           0 :                                                      rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor );
    1391             :                             else
    1392             :                                 EMFPPlusDrawPolygon( polyPolygon,
    1393           0 :                                                      rFactoryParms, rState, rCanvas, flags & 0xff );
    1394             :                         }
    1395           0 :                         break;
    1396             :                     case EmfPlusRecordTypeFillRects:
    1397             :                         {
    1398             :                             SAL_INFO("cppcanvas.emf", "EMF+ FillRects");
    1399             : 
    1400             :                             sal_uInt32 brushIndexOrColor;
    1401             :                             sal_Int32 rectangles;
    1402           0 :                             bool isColor = (flags & 0x8000);
    1403           0 :                             ::basegfx::B2DPolygon polygon;
    1404             : 
    1405           0 :                             rMF >> brushIndexOrColor >> rectangles;
    1406             : 
    1407             :                             SAL_INFO("cppcanvas.emf", "EMF+\t" << ((flags & 0x8000) ? "color" : "brush index") << ": 0x" << std::hex << brushIndexOrColor << std::dec);
    1408             : 
    1409           0 :                             for (int i=0; i < rectangles; i++) {
    1410           0 :                                 if (flags & 0x4000) {
    1411             :                                     /* 16bit integers */
    1412             :                                     sal_Int16 x, y, width, height;
    1413             : 
    1414           0 :                                     rMF >> x >> y >> width >> height;
    1415             : 
    1416           0 :                                     polygon.append (Map (x, y));
    1417           0 :                                     polygon.append (Map (x + width, y));
    1418           0 :                                     polygon.append (Map (x + width, y + height));
    1419           0 :                                     polygon.append (Map (x, y + height));
    1420             : 
    1421             :                                     SAL_INFO("cppcanvas.emf", "EMF+\trectangle: " << x << "," << " " << width << "x" << height);
    1422             :                                 } else {
    1423             :                                     /* Single's */
    1424             :                                     float x, y, width, height;
    1425             : 
    1426           0 :                                     rMF >> x >> y >> width >> height;
    1427             : 
    1428           0 :                                     polygon.append (Map (x, y));
    1429           0 :                                     polygon.append (Map (x + width, y));
    1430           0 :                                     polygon.append (Map (x + width, y + height));
    1431           0 :                                     polygon.append (Map (x, y + height));
    1432             : 
    1433             :                                     SAL_INFO("cppcanvas.emf", "EMF+\trectangle: " << x << "," << " " << width << "x" << height);
    1434             :                                 }
    1435             : 
    1436           0 :                                 ::basegfx::B2DPolyPolygon polyPolygon (polygon);
    1437             : 
    1438             :                                 // n#812793: EMF+ Seems to specify transparent background with Alpha=0xFF !
    1439             :                                 // Workaround for the problem.
    1440           0 :                                 if( isColor && brushIndexOrColor == 0xFFFFFFFF && rectangles == 1 )
    1441           0 :                                     brushIndexOrColor = 0xFFFFFF;
    1442             : 
    1443           0 :                                 EMFPPlusFillPolygon (polyPolygon, rFactoryParms, rState, rCanvas, isColor, brushIndexOrColor);
    1444           0 :                             }
    1445           0 :                             break;
    1446             :                         }
    1447             :                     case EmfPlusRecordTypeFillPolygon:
    1448             :                         {
    1449           0 :                             sal_uInt8 index = flags & 0xff;
    1450             :                             sal_uInt32 brushIndexOrColor;
    1451             :                             sal_Int32 points;
    1452             : 
    1453           0 :                             rMF >> brushIndexOrColor;
    1454           0 :                             rMF >> points;
    1455             : 
    1456             :                             SAL_INFO("cppcanvas.emf", "EMF+ FillPolygon in slot: " << +index << " points: " << points);
    1457             :                             SAL_INFO("cppcanvas.emf", "EMF+\t: " << ((flags & 0x8000) ? "color" : "brush index") << " 0x" << std::hex << brushIndexOrColor << std::dec);
    1458             : 
    1459           0 :                             EMFPPath path (points, true);
    1460           0 :                             path.Read (rMF, flags, *this);
    1461             : 
    1462           0 :                             EMFPPlusFillPolygon (path.GetPolygon (*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
    1463             : 
    1464           0 :                             break;
    1465             :                         }
    1466             :                     case EmfPlusRecordTypeDrawLines:
    1467             :                         {
    1468             :                             sal_uInt32 points;
    1469             : 
    1470           0 :                             rMF >> points;
    1471             : 
    1472             :                             SAL_INFO("cppcanvas.emf", "EMF+ DrawLines in slot: " << (flags && 0xff) << " points: " << points);
    1473             : 
    1474           0 :                             EMFPPath path (points, true);
    1475           0 :                             path.Read (rMF, flags, *this);
    1476             : 
    1477           0 :                             EMFPPlusDrawPolygon (path.GetPolygon (*this), rFactoryParms, rState, rCanvas, flags);
    1478             : 
    1479           0 :                             break;
    1480             :                         }
    1481             :                     case EmfPlusRecordTypeDrawPath:
    1482             :                         {
    1483             :                             sal_uInt32 penIndex;
    1484             : 
    1485           0 :                             rMF >> penIndex;
    1486             : 
    1487             :                             SAL_INFO("cppcanvas.emf", "EMF+ DrawPath");
    1488             :                             SAL_INFO("cppcanvas.emf", "EMF+\tpen: " << penIndex);
    1489             : 
    1490           0 :                             EMFPPath* path = (EMFPPath*) aObjects [flags & 0xff];
    1491             :                             SAL_WARN_IF( !path, "cppcanvas.emf", "EmfPlusRecordTypeDrawPath missing path" );
    1492             : 
    1493           0 :                             EMFPPlusDrawPolygon (path->GetPolygon (*this), rFactoryParms, rState, rCanvas, penIndex);
    1494             : 
    1495           0 :                             break;
    1496             :                         }
    1497             :                     case EmfPlusRecordTypeDrawImage:
    1498             :                     case EmfPlusRecordTypeDrawImagePoints:
    1499             :                         {
    1500             :                             sal_uInt32 attrIndex;
    1501             :                             sal_Int32 sourceUnit;
    1502             : 
    1503           0 :                             rMF >> attrIndex >> sourceUnit;
    1504             : 
    1505             :                             SAL_INFO("cppcanvas.emf", "EMF+ " << (type == EmfPlusRecordTypeDrawImagePoints ? "DrawImagePoints" : "DrawImage") << "attributes index: " << attrIndex << "source unit: " << sourceUnit);
    1506             :                             SAL_INFO("cppcanvas.emf", "EMF+\tTODO: use image attributes");
    1507             : 
    1508           0 :                             if (sourceUnit == 2 && aObjects [flags & 0xff]) { // we handle only GraphicsUnit.Pixel now
    1509           0 :                                 EMFPImage& image = *(EMFPImage *) aObjects [flags & 0xff];
    1510             :                                 float sx, sy, sw, sh;
    1511             :                                 sal_Int32 aCount;
    1512             : 
    1513           0 :                                 ReadRectangle (rMF, sx, sy, sw, sh);
    1514             : 
    1515             :                                 SAL_INFO("cppcanvas.emf", "EMF+ " << (type == EmfPlusRecordTypeDrawImagePoints ? "DrawImagePoints" : "DrawImage") << " source rectangle: " << sx << "," << sy << " " << sw << "x" << sh);
    1516             : 
    1517           0 :                                 ::basegfx::B2DPoint aDstPoint;
    1518           0 :                                 ::basegfx::B2DSize aDstSize;
    1519           0 :                                 bool bValid = false;
    1520             : 
    1521           0 :                                 if (type == EmfPlusRecordTypeDrawImagePoints) {
    1522           0 :                                     rMF >> aCount;
    1523             : 
    1524           0 :                                     if( aCount == 3) { // TODO: now that we now that this value is count we should support it better
    1525             :                                         float x1, y1, x2, y2, x3, y3;
    1526             : 
    1527           0 :                                         ReadPoint (rMF, x1, y1, flags);
    1528           0 :                                         ReadPoint (rMF, x2, y2, flags);
    1529           0 :                                         ReadPoint (rMF, x3, y3, flags);
    1530             : 
    1531             :                                         SAL_INFO("cppcanvas.emf", "EMF+ destination points: " << x1 << "," << y1 << " " << x2 << "," << y2 << " " << x3 << "," << y3);
    1532             :                                         SAL_INFO("cppcanvas.emf", "EMF+ destination rectangle: " << x1 << "," << y1 << " " << x2 - x1 << "x" << y3 - y1);
    1533             : 
    1534           0 :                                         aDstPoint = Map (x1, y1);
    1535           0 :                                         aDstSize = MapSize(x2 - x1, y3 - y1);
    1536             : 
    1537           0 :                                         bValid = true;
    1538             :                                     }
    1539           0 :                                 } else if (type == EmfPlusRecordTypeDrawImage) {
    1540             :                                     float dx, dy, dw, dh;
    1541             : 
    1542           0 :                                     ReadRectangle (rMF, dx, dy, dw, dh, flags & 0x4000);
    1543             : 
    1544             :                                     SAL_INFO("cppcanvas.emf", "EMF+ destination rectangle: " << dx << "," << dy << " " << dw << "x" << dh);
    1545             : 
    1546           0 :                                     aDstPoint = Map (dx, dy);
    1547           0 :                                     aDstSize = MapSize(dw, dh);
    1548             : 
    1549           0 :                                     bValid = true;
    1550             :                                 }
    1551             : 
    1552           0 :                                 if (bValid) {
    1553           0 :                                     BitmapEx aBmp( image.graphic.GetBitmapEx () );
    1554             : 
    1555           0 :                                     Size aSize( aBmp.GetSizePixel() );
    1556             :                                     SAL_INFO("cppcanvas.emf", "EMF+ bitmap size: " << aSize.Width() << "x" << aSize.Height());
    1557           0 :                                     if( aSize.Width() > 0 && aSize.Height() > 0 ) {
    1558             :                                         ActionSharedPtr pBmpAction (
    1559             :                                             internal::BitmapActionFactory::createBitmapAction (
    1560             :                                                 aBmp,
    1561           0 :                                                 rState.mapModeTransform * aDstPoint,
    1562           0 :                                                 rState.mapModeTransform * aDstSize,
    1563             :                                                 rCanvas,
    1564           0 :                                                 rState));
    1565             : 
    1566           0 :                                         if( pBmpAction ) {
    1567             :                                             maActions.push_back( MtfAction( pBmpAction,
    1568           0 :                                                                             rFactoryParms.mrCurrActionIndex ) );
    1569             : 
    1570           0 :                                             rFactoryParms.mrCurrActionIndex += pBmpAction->getActionCount()-1;
    1571           0 :                                         }
    1572             :                                     } else {
    1573             :                                         SAL_INFO("cppcanvas.emf", "EMF+ warning: empty bitmap");
    1574           0 :                                     }
    1575             :                                 } else {
    1576             :                                     SAL_INFO("cppcanvas.emf", "EMF+ DrawImage(Points) TODO (fixme)");
    1577           0 :                                 }
    1578             :                             } else {
    1579             :                                 SAL_INFO("cppcanvas.emf", "EMF+ DrawImage(Points) TODO (fixme) - possibly unsupported source units for crop rectangle");
    1580             :                             }
    1581           0 :                             break;
    1582             :                         }
    1583             :                     case EmfPlusRecordTypeDrawString:
    1584             :                         {
    1585             :                             SAL_INFO("cppcanvas.emf", "EMF+ DrawString");
    1586             : 
    1587             :                             sal_uInt32 brushId;
    1588             :                             sal_uInt32 formatId;
    1589             :                             sal_uInt32 stringLength;
    1590             : 
    1591           0 :                             rMF >> brushId >> formatId >> stringLength;
    1592             :                             SAL_INFO("cppcanvas.emf", "EMF+ DrawString brushId: " << brushId << " formatId: " << formatId << " length: " << stringLength);
    1593             : 
    1594           0 :                             if (flags & 0x8000) {
    1595             :                                 float lx, ly, lw, lh;
    1596             : 
    1597           0 :                                 rMF >> lx >> ly >> lw >> lh;
    1598             : 
    1599             :                                 SAL_INFO("cppcanvas.emf", "EMF+ DrawString layoutRect: " << lx << "," << ly << " - " << lw << "x" << lh);
    1600             : 
    1601           0 :                                 OUString text = read_uInt16s_ToOUString(rMF, stringLength);
    1602             : 
    1603           0 :                                 double cellSize = setFont (flags & 0xff, rFactoryParms, rState);
    1604           0 :                                 rState.textColor = COLOR( brushId );
    1605             : 
    1606           0 :                                 ::basegfx::B2DPoint point( Map( lx + 0.15*cellSize, ly + cellSize ) );
    1607             : 
    1608             :                                 ActionSharedPtr pTextAction(
    1609             :                                     TextActionFactory::createTextAction(
    1610             :                                                                         // position is just rough guess for now
    1611             :                                                                         // we should calculate it exactly from layoutRect or font
    1612             :                                         ::vcl::unotools::pointFromB2DPoint ( point ),
    1613             :                                         ::Size(),
    1614             :                                         ::Color(),
    1615             :                                         ::Size(),
    1616             :                                         ::Color(),
    1617             :                                         text,
    1618             :                                         0,
    1619             :                                         stringLength,
    1620             :                                         NULL,
    1621             :                                         rFactoryParms.mrVDev,
    1622             :                                         rFactoryParms.mrCanvas,
    1623             :                                         rState,
    1624             :                                         rFactoryParms.mrParms,
    1625           0 :                                         false ) );
    1626           0 :                                 if( pTextAction )
    1627             :                                 {
    1628             :                                     SAL_INFO("cppcanvas.emf", "EMF+\t\tadd text action");
    1629             : 
    1630             :                                     maActions.push_back(
    1631             :                                                         MtfAction(
    1632             :                                                                   pTextAction,
    1633           0 :                                                                   rFactoryParms.mrCurrActionIndex ) );
    1634             : 
    1635           0 :                                     rFactoryParms.mrCurrActionIndex += pTextAction->getActionCount()-1;
    1636           0 :                                 }
    1637             :                             } else {
    1638             :                                 SAL_INFO("cppcanvas.emf", "EMF+ DrawString TODO - drawing with brush not yet supported");
    1639             :                             }
    1640             :                         }
    1641           0 :                         break;
    1642             :                     case EmfPlusRecordTypeSetPageTransform:
    1643           0 :                         rMF >> fPageScale;
    1644             : 
    1645             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetPageTransform");
    1646             :                         SAL_INFO("cppcanvas.emf", "EMF+\tscale: " << fPageScale << " unit: " << flags);
    1647             :                         SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    1648           0 :                         break;
    1649             :                     case EmfPlusRecordTypeSetRenderingOrigin:
    1650           0 :                         rMF >> nOriginX >> nOriginY;
    1651             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetRenderingOrigin");
    1652             :                         SAL_INFO("cppcanvas.emf", "EMF+\torigin [x,y]: " << nOriginX << "," << nOriginY);
    1653           0 :                         break;
    1654             :                     case EmfPlusRecordTypeSetTextRenderingHint:
    1655             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetTextRenderingHint");
    1656             :                         SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    1657           0 :                         break;
    1658             :                     case EmfPlusRecordTypeSetAntiAliasMode:
    1659             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetAntiAliasMode");
    1660             :                         SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    1661           0 :                         break;
    1662             :                     case EmfPlusRecordTypeSetInterpolationMode:
    1663             :                         SAL_INFO("cppcanvas.emf", "EMF+ InterpolationMode");
    1664             :                         SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    1665           0 :                         break;
    1666             :                     case EmfPlusRecordTypeSetPixelOffsetMode:
    1667             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetPixelOffsetMode");
    1668             :                         SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    1669           0 :                         break;
    1670             :                     case EmfPlusRecordTypeSetCompositingQuality:
    1671             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetCompositingQuality");
    1672             :                         SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    1673           0 :                         break;
    1674             :                     case EmfPlusRecordTypeSave:
    1675             :                     {
    1676             :                         sal_uInt32 stackIndex;
    1677             : 
    1678           0 :                         rMF >> stackIndex;
    1679             : 
    1680             :                         SAL_INFO("cppcanvas.emf", "EMF+ Save stack index: " << stackIndex);
    1681             : 
    1682           0 :                         GraphicStatePush( mGSStack, stackIndex, rState );
    1683             : 
    1684           0 :                         break;
    1685             :                     }
    1686             :                     case EmfPlusRecordTypeRestore:
    1687             :                     {
    1688             :                         sal_uInt32 stackIndex;
    1689             : 
    1690           0 :                         rMF >> stackIndex;
    1691             : 
    1692             :                         SAL_INFO("cppcanvas.emf", "EMF+ Restore stack index: " << stackIndex);
    1693             : 
    1694           0 :                         GraphicStatePop( mGSStack, stackIndex, rState );
    1695             : 
    1696           0 :                         break;
    1697             :                     }
    1698             :                     case EmfPlusRecordTypeBeginContainerNoParams:
    1699             :                     {
    1700             :                         sal_uInt32 stackIndex;
    1701             : 
    1702           0 :                         rMF >> stackIndex;
    1703             : 
    1704             :                         SAL_INFO("cppcanvas.emf", "EMF+ Begin Container No Params stack index: " << stackIndex);
    1705             : 
    1706           0 :                         GraphicStatePush( mGSContainerStack, stackIndex, rState );
    1707             :                     }
    1708           0 :                     break;
    1709             :                     case EmfPlusRecordTypeEndContainer:
    1710             :                     {
    1711             :                         sal_uInt32 stackIndex;
    1712             : 
    1713           0 :                         rMF >> stackIndex;
    1714             : 
    1715             :                         SAL_INFO("cppcanvas.emf", "EMF+ End Container stack index: " << stackIndex);
    1716             : 
    1717           0 :                         GraphicStatePop( mGSContainerStack, stackIndex, rState );
    1718             :                     }
    1719           0 :                     break;
    1720             :                     case EmfPlusRecordTypeSetWorldTransform: {
    1721             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetWorldTransform");
    1722           0 :                         XForm transform;
    1723           0 :                         rMF >> transform;
    1724           0 :                         aWorldTransform.Set (transform);
    1725             :                         SAL_INFO("cppcanvas.emf",
    1726             :                                 "EMF+\tm11: " << aWorldTransform.eM11 << "\tm12: " << aWorldTransform.eM12 <<
    1727             :                                 "\tm21: " << aWorldTransform.eM21 << "\tm22: " << aWorldTransform.eM22 <<
    1728             :                                 "\tdx: "  << aWorldTransform.eDx  << "\tdy: "  << aWorldTransform.eDy);
    1729           0 :                         break;
    1730             :                     }
    1731             :                     case EmfPlusRecordTypeResetWorldTransform:
    1732             :                         SAL_INFO("cppcanvas.emf", "EMF+ ResetWorldTransform");
    1733           0 :                         aWorldTransform.SetIdentity ();
    1734           0 :                         break;
    1735             :                     case EmfPlusRecordTypeMultiplyWorldTransform: {
    1736             :                         SAL_INFO("cppcanvas.emf", "EMF+ MultiplyWorldTransform");
    1737           0 :                         XForm transform;
    1738           0 :                         rMF >> transform;
    1739             : 
    1740             :                         SAL_INFO("cppcanvas.emf",
    1741             :                                 "EMF+\tmatrix m11: " << transform.eM11 << "m12: " << transform.eM12 <<
    1742             :                                 "EMF+\tm21: "        << transform.eM21 << "m22: " << transform.eM22 <<
    1743             :                                 "EMF+\tdx: "         << transform.eDx  << "dy: "  << transform.eDy);
    1744             : 
    1745           0 :                         if (flags & 0x2000)  // post multiply
    1746           0 :                             aWorldTransform.Multiply (transform);
    1747             :                         else {               // pre multiply
    1748           0 :                             transform.Multiply (aWorldTransform);
    1749           0 :                             aWorldTransform.Set (transform);
    1750             :                         }
    1751             :                         SAL_INFO("cppcanvas.emf",
    1752             :                                 "EMF+\tm11: " << aWorldTransform.eM11 << "m12: " << aWorldTransform.eM12 <<
    1753             :                                 "EMF+\tm21: " << aWorldTransform.eM21 << "m22: " << aWorldTransform.eM22 <<
    1754             :                                 "EMF+\tdx: "  << aWorldTransform.eDx  << "dy: "  << aWorldTransform.eDy);
    1755           0 :                         break;
    1756             :                     }
    1757             :                     case EmfPlusRecordTypeSetClipRect:
    1758             :                         {
    1759           0 :                             int combineMode = (flags >> 8) & 0xf;
    1760             : 
    1761             :                             SAL_INFO("cppcanvas.emf", "EMF+ SetClipRect combine mode: " << combineMode);
    1762             : #if OSL_DEBUG_LEVEL > 1
    1763             :                             if (combineMode > 1) {
    1764             :                                 SAL_INFO ("cppcanvas.emf", "EMF+ TODO combine mode > 1");
    1765             :                             }
    1766             : #endif
    1767             : 
    1768             :                             float dx, dy, dw, dh;
    1769             : 
    1770           0 :                             ReadRectangle (rMF, dx, dy, dw, dh, false);
    1771             : 
    1772             :                             SAL_INFO("cppcanvas.emf", "EMF+ RectData: " << dx << "," << dy << " " << dw << "x" << dh);
    1773             : 
    1774           0 :                             B2DPoint mappedPoint (Map (dx, dy));
    1775           0 :                             B2DSize mappedSize( MapSize (dw, dh));
    1776             : 
    1777             :                             ::basegfx::B2DPolyPolygon polyPolygon( ::basegfx::B2DPolygon( ::basegfx::tools::createPolygonFromRect( ::basegfx::B2DRectangle( mappedPoint.getX(), mappedPoint.getY(),
    1778           0 :                                                                                                                                                             mappedPoint.getX() + mappedSize.getX(),
    1779           0 :                                                                                                                                                             mappedPoint.getY() + mappedSize.getY() ) ) ) );
    1780           0 :                             polyPolygon.transform(rState.mapModeTransform);
    1781             : 
    1782           0 :                             updateClipping (polyPolygon, rFactoryParms, combineMode == 1);
    1783             : 
    1784           0 :                             break;
    1785             :                         }
    1786             :                     case EmfPlusRecordTypeSetClipPath:
    1787             :                         {
    1788           0 :                             int combineMode = (flags >> 8) & 0xf;
    1789             : 
    1790             :                             SAL_INFO("cppcanvas.emf", "EMF+ SetClipPath combine mode: " << combineMode);
    1791             :                             SAL_INFO("cppcanvas.emf", "EMF+\tpath in slot: " << (flags & 0xff));
    1792             : 
    1793           0 :                             EMFPPath& path = *(EMFPPath*) aObjects [flags & 0xff];
    1794           0 :                             ::basegfx::B2DPolyPolygon& clipPoly (path.GetPolygon (*this));
    1795             : 
    1796           0 :                             clipPoly.transform (rState.mapModeTransform);
    1797           0 :                             updateClipping (clipPoly, rFactoryParms, combineMode == 1);
    1798             : 
    1799           0 :                             break;
    1800             :                         }
    1801             :                     case EmfPlusRecordTypeSetClipRegion: {
    1802           0 :                         int combineMode = (flags >> 8) & 0xf;
    1803             : 
    1804             :                         SAL_INFO("cppcanvas.emf", "EMF+ SetClipRegion");
    1805             :                         SAL_INFO("cppcanvas.emf", "EMF+\tregion in slot: " << (flags & 0xff) << " combine mode: " << combineMode);
    1806           0 :                         EMFPRegion *region = (EMFPRegion*)aObjects [flags & 0xff];
    1807             : 
    1808             :                         // reset clip
    1809           0 :                         if (region && region->parts == 0 && region->initialState == EmfPlusRegionInitialStateInfinite) {
    1810           0 :                             updateClipping (::basegfx::B2DPolyPolygon (), rFactoryParms, combineMode == 1);
    1811             :                         } else {
    1812             :                             SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    1813             :                         }
    1814           0 :                         break;
    1815             :                     }
    1816             :                     case EmfPlusRecordTypeDrawDriverString: {
    1817             :                         SAL_INFO("cppcanvas.emf", "EMF+ DrawDriverString, flags: 0x" << std::hex << flags << std::dec);
    1818             :                         sal_uInt32 brushIndexOrColor;
    1819             :                         sal_uInt32 optionFlags;
    1820             :                         sal_uInt32 hasMatrix;
    1821             :                         sal_uInt32 glyphsCount;
    1822             : 
    1823           0 :                         rMF >> brushIndexOrColor >> optionFlags >> hasMatrix >> glyphsCount;
    1824             : 
    1825             :                         SAL_INFO("cppcanvas.emf", "EMF+\t: " << ((flags & 0x8000) ? "color" : "brush index") << " 0x" << std::hex << brushIndexOrColor << std::dec);
    1826             :                         SAL_INFO("cppcanvas.emf", "EMF+\toption flags: 0x" << std::hex << optionFlags << std::dec);
    1827             :                         SAL_INFO("cppcanvas.emf", "EMF+\thas matrix: " << hasMatrix);
    1828             :                         SAL_INFO("cppcanvas.emf", "EMF+\tglyphs: " << glyphsCount);
    1829             : 
    1830           0 :                         if( ( optionFlags & 1 ) && glyphsCount > 0 ) {
    1831           0 :                             float *charsPosX = new float[glyphsCount];
    1832           0 :                             float *charsPosY = new float[glyphsCount];
    1833             : 
    1834           0 :                             OUString text = read_uInt16s_ToOUString(rMF, glyphsCount);
    1835             : 
    1836           0 :                             for( sal_uInt32 i=0; i<glyphsCount; i++) {
    1837           0 :                                 rMF >> charsPosX[i] >> charsPosY[i];
    1838             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tglyphPosition[" << i << "]: " << charsPosX[i] << "," << charsPosY[i]);
    1839             :                             }
    1840             : 
    1841           0 :                             XForm transform;
    1842           0 :                             if( hasMatrix ) {
    1843           0 :                                 rMF >> transform;
    1844             :                                 SAL_INFO("cppcanvas.emf", "EMF+\tmatrix: " << transform.eM11 << ", " << transform.eM12 << ", " << transform.eM21 << ", " << transform.eM22 << ", " << transform.eDx << ", " << transform.eDy);
    1845             :                             }
    1846             : 
    1847             :                             // add the text action
    1848           0 :                             setFont (flags & 0xff, rFactoryParms, rState);
    1849             : 
    1850           0 :                             if( flags & 0x8000 )
    1851           0 :                                 rState.textColor = COLOR( brushIndexOrColor );
    1852             : 
    1853           0 :                             ::basegfx::B2DPoint point( Map( charsPosX[0], charsPosY[0] ) );
    1854             : 
    1855             :                             ActionSharedPtr pTextAction(
    1856             :                                     TextActionFactory::createTextAction(
    1857             :                                         ::vcl::unotools::pointFromB2DPoint ( point ),
    1858             :                                         ::Size(),
    1859             :                                         ::Color(),
    1860             :                                         ::Size(),
    1861             :                                         ::Color(),
    1862             :                                         text,
    1863             :                                         0,
    1864             :                                         glyphsCount,
    1865             :                                         NULL,
    1866             :                                         rFactoryParms.mrVDev,
    1867             :                                         rFactoryParms.mrCanvas,
    1868             :                                         rState,
    1869             :                                         rFactoryParms.mrParms,
    1870           0 :                                         false ) );
    1871             : 
    1872           0 :                             if( pTextAction )
    1873             :                             {
    1874             :                                 SAL_INFO("cppcanvas.emf", "EMF+\t\tadd text action");
    1875             : 
    1876             :                                 maActions.push_back(
    1877             :                                         MtfAction(
    1878             :                                             pTextAction,
    1879           0 :                                             rFactoryParms.mrCurrActionIndex ) );
    1880             : 
    1881           0 :                                 rFactoryParms.mrCurrActionIndex += pTextAction->getActionCount()-1;
    1882             :                             }
    1883             : 
    1884           0 :                             delete[] charsPosX;
    1885           0 :                             delete[] charsPosY;
    1886             :                         } else {
    1887             :                             SAL_INFO("cppcanvas.emf", "EMF+\tTODO: fonts (non-unicode glyphs chars)");
    1888             :                         }
    1889             : 
    1890           0 :                         break;
    1891             :                     }
    1892             :                     default:
    1893             :                         SAL_INFO("cppcanvas.emf", "EMF+ unhandled record type: " << type);
    1894             :                         SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
    1895             :                     }
    1896             :                 }
    1897             : 
    1898           0 :                 rMF.Seek (next);
    1899             : 
    1900           0 :                 if (size <= length)
    1901             :                 {
    1902           0 :                     length -= size;
    1903             :                 }
    1904             :                 else
    1905             :                 {
    1906             :                     SAL_WARN("cppcanvas.emf", "ImplRenderer::processEMFPlus: "
    1907             :                             "size " << size << " > length " << length);
    1908             : #if OSL_DEBUG_LEVEL > 1
    1909             :                     dumpWords(rMF, length);
    1910             : #endif
    1911           0 :                     length = 0;
    1912             :                 }
    1913           0 :             }
    1914           0 :         }
    1915             :     }
    1916         411 : }
    1917             : 
    1918             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10