LCOV - code coverage report
Current view: top level - libreoffice/cppcanvas/source/mtfrenderer - emfplus.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 659 0.0 %
Date: 2012-12-27 Functions: 0 39 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10