update dev300-m58
[ooovba.git] / applied_patches / 0482-emf+-cppcanvas-emfplus.diff
blobc5be3af15f87549f1909620e83dc6f425420991a
1 --- cppcanvas/source/inc/implrenderer.hxx.old 2009-04-02 11:06:59.000000000 +0000
2 +++ cppcanvas/source/inc/implrenderer.hxx 2009-04-06 16:42:16.000000000 +0000
3 @@ -50,6 +50,11 @@ class Gradient;
4 class BitmapEx;
5 class MapMode;
6 class Size;
7 +class Rectangle;
8 +class Font;
9 +class PolyPolygon;
10 +class Point;
11 +class MetaCommentAction;
13 namespace basegfx {
14 class B2DPolyPolygon;
15 @@ -63,11 +68,110 @@ namespace cppcanvas
17 struct OutDevState;
18 struct ActionFactoryParameters;
19 + struct EMFPObject;
20 + struct XForm;
22 // state stack of OutputDevice, to correctly handle
23 // push/pop actions
24 typedef ::std::vector< OutDevState > VectorOfOutDevStates;
26 + // EMF+
27 + // TODO: replace?
28 + struct XForm
29 + {
30 + float eM11;
31 + float eM12;
32 + float eM21;
33 + float eM22;
34 + float eDx;
35 + float eDy;
36 + XForm()
37 + {
38 + SetIdentity ();
39 + };
41 + void SetIdentity ()
42 + {
43 + eM11 = eM22 = 1.0f;
44 + eDx = eDy = eM12 = eM21 = 0.0f;
45 + }
47 + void Set (float m11, float m12, float dx, float m21, float m22, float dy)
48 + {
49 + eM11 = m11;
50 + eM12 = m12;
51 + eDx = dx;
52 + eM21 = m21;
53 + eM22 = m22;
54 + eDy = dy;
55 + }
57 + void Set (XForm f)
58 + {
59 + eM11 = f.eM11;
60 + eM12 = f.eM12;
61 + eM21 = f.eM21;
62 + eM22 = f.eM22;
63 + eDx = f.eDx;
64 + eDy = f.eDy;
65 + }
67 + void Multiply (float m11, float m12, float dx, float m21, float m22, float dy)
68 + {
69 + eM11 = eM11*m11 + eM12*m21;
70 + eM12 = eM11*m12 + eM12*m22;
71 + eM21 = eM21*m11 + eM22*m21;
72 + eM22 = eM21*m12 + eM22*m22;
73 + eDx *= eDx*m11 + eDy*m21 + dx;
74 + eDy *= eDx*m12 + eDy*m22 + dy;
75 + }
77 + void Multiply (XForm f)
78 + {
79 + eM11 = eM11*f.eM11 + eM12*f.eM21;
80 + eM12 = eM11*f.eM12 + eM12*f.eM22;
81 + eM21 = eM21*f.eM11 + eM22*f.eM21;
82 + eM22 = eM21*f.eM12 + eM22*f.eM22;
83 + eDx *= eDx*f.eM11 + eDy*f.eM21 + f.eDx;
84 + eDy *= eDx*f.eM12 + eDy*f.eM22 + f.eDy;
85 + }
87 +#ifdef OSL_BIGENDIAN
88 +// currently unused
89 +static float GetSwapFloat( SvStream& rSt )
91 + float fTmp;
92 + sal_Int8* pPtr = (sal_Int8*)&fTmp;
93 + rSt >> pPtr[3] >> pPtr[2] >> pPtr[1] >> pPtr[0]; // Little Endian <-> Big Endian switch
94 + return fTmp;
96 +#endif
98 + friend SvStream& operator>>( SvStream& rIn, XForm& rXForm )
99 + {
100 + if ( sizeof( float ) != 4 )
102 + DBG_ERROR( "EnhWMFReader::sizeof( float ) != 4" );
103 + rXForm = XForm();
105 + else
107 +#ifdef OSL_BIGENDIAN
108 + rXForm.eM11 = GetSwapFloat( rIn );
109 + rXForm.eM12 = GetSwapFloat( rIn );
110 + rXForm.eM21 = GetSwapFloat( rIn );
111 + rXForm.eM22 = GetSwapFloat( rIn );
112 + rXForm.eDx = GetSwapFloat( rIn );
113 + rXForm.eDy = GetSwapFloat( rIn );
114 +#else
115 + rIn >> rXForm.eM11 >> rXForm.eM12 >> rXForm.eM21 >> rXForm.eM22
116 + >> rXForm.eDx >> rXForm.eDy;
117 +#endif
119 + return rIn;
121 + };
123 class ImplRenderer : public virtual Renderer, protected CanvasGraphicHelper
125 public:
126 @@ -106,6 +210,14 @@ namespace cppcanvas
127 // (externally not visible)
128 typedef ::std::vector< MtfAction > ActionVector;
130 + /* EMF+ */
131 + void ReadRectangle (SvStream& s, float& x, float& y, float &width, float& height, sal_uInt32 flags = 0);
132 + void ReadPoint (SvStream& s, float& x, float& y, sal_uInt32 flags = 0);
133 + void MapToDevice (double &x, double &y);
134 + ::basegfx::B2DPoint Map (::basegfx::B2DPoint& p);
135 + ::basegfx::B2DPoint Map (double ix, double iy);
136 + ::basegfx::B2DSize MapSize (double iwidth, double iheight);
137 + ::basegfx::B2DRange MapRectangle (double ix, double iy, double iwidth, double iheight);
139 private:
140 // default: disabled copy/assignment
141 @@ -158,8 +270,30 @@ namespace cppcanvas
142 ActionVector::const_iterator& o_rRangeBegin,
143 ActionVector::const_iterator& o_rRangeEnd ) const;
145 + void processEMFPlus( MetaCommentAction* pAct, const ActionFactoryParameters& rFactoryParms, OutDevState& rState, const CanvasSharedPtr& rCanvas );
146 + void EMFPPlusFillPolygon (::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms, OutDevState& rState, const CanvasSharedPtr& rCanvas, bool isColor, sal_uInt32 brushIndexOrColor);
148 ActionVector maActions;
150 + /* EMF+ */
151 + XForm aBaseTransform;
152 + XForm aWorldTransform;
153 + EMFPObject* aObjects [256];
154 + float fPageScale;
155 + sal_Int32 nOriginX;
156 + sal_Int32 nOriginY;
157 + sal_Int32 nHDPI;
158 + sal_Int32 nVDPI;
159 + ::PolyPolygon aClippingPolygon;
160 + /* EMF+ emf header info */
161 + sal_Int32 nFrameLeft;
162 + sal_Int32 nFrameTop;
163 + sal_Int32 nFrameRight;
164 + sal_Int32 nFrameBottom;
165 + sal_Int32 nPixX;
166 + sal_Int32 nPixY;
167 + sal_Int32 nMmX;
168 + sal_Int32 nMmY;
172 --- cppcanvas/util/makefile.mk
173 +++ cppcanvas/util/makefile.mk
174 @@ -55,7 +55,7 @@
176 SHL1TARGET= $(TARGET)$(DLLPOSTFIX)
177 SHL1IMPLIB= i$(TARGET)
178 -SHL1STDLIBS= $(TOOLSLIB) $(CPPULIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CANVASTOOLSLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(I18NISOLANGLIB)
179 +SHL1STDLIBS= $(TOOLSLIB) $(CPPULIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CANVASTOOLSLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(I18NISOLANGLIB) $(SVTOOLLIB)
181 .IF "$(debug)$(dbgutil)"!=""
182 SHL1STDLIBS += $(CPPUHELPERLIB)
183 --- cppcanvas/source/mtfrenderer/makefile.mk.old 2009-04-02 11:06:59.000000000 +0000
184 +++ cppcanvas/source/mtfrenderer/makefile.mk 2009-04-06 16:42:16.000000000 +0000
185 @@ -48,6 +48,7 @@ CDEFS+= -DVERBOSE
187 SLOFILES = $(SLO)$/cachedprimitivebase.obj \
188 $(SLO)$/bitmapaction.obj \
189 + $(SLO)$/emfplus.obj \
190 $(SLO)$/implrenderer.obj \
191 $(SLO)$/lineaction.obj \
192 $(SLO)$/pointaction.obj \
193 --- cppcanvas/source/mtfrenderer/implrenderer.cxx.old 2009-04-02 11:06:59.000000000 +0000
194 +++ cppcanvas/source/mtfrenderer/implrenderer.cxx 2009-04-06 16:42:16.000000000 +0000
195 @@ -105,6 +105,8 @@
196 #include "mtftools.hxx"
197 #include "outdevstate.hxx"
199 +#define EMFP_DEBUG(x)
200 +//#define EMFP_DEBUG(x) x
202 using namespace ::com::sun::star;
204 @@ -1902,6 +1904,33 @@ namespace cppcanvas
208 + // Handle drawing layer fills
209 + else if( pAct->GetComment().Equals( "EMF_PLUS" ) ) {
210 + static int count = -1, limit = 0x7fffffff;
211 + if (count == -1) {
212 + count = 0;
213 + char *env;
214 + if (env = getenv ("EMF_PLUS_LIMIT")) {
215 + limit = atoi (env);
218 + EMFP_DEBUG (printf ("EMF+ passed to canvas mtf renderer, size: %d\n", pAct->GetDataSize ()));
219 + if (count < limit)
220 + processEMFPlus( pAct, rFactoryParms, getState( rStates ), rCanvas );
221 + count ++;
222 + } else if( pAct->GetComment().Equals( "EMF_PLUS_HEADER_INFO" ) ) {
223 + EMFP_DEBUG (printf ("EMF+ passed to canvas mtf renderer - header info, size: %d\n", pAct->GetDataSize ()));
225 + SvMemoryStream rMF ((void*) pAct->GetData (), pAct->GetDataSize (), STREAM_READ);
227 + rMF >> nFrameLeft >> nFrameTop >> nFrameRight >> nFrameBottom;
228 + EMFP_DEBUG (printf ("EMF+ picture frame: %d,%d - %d,%d\n", nFrameLeft, nFrameTop, nFrameRight, nFrameBottom));
229 + rMF >> nPixX >> nPixY >> nMmX >> nMmY;
230 + EMFP_DEBUG (printf ("EMF+ ref device pixel size: %dx%d mm size: %dx%d\n", nPixX, nPixY, nMmX, nMmY));
232 + rMF >> aBaseTransform;
233 + //aWorldTransform.Set (aBaseTransform);
236 break;
238 @@ -3070,6 +3099,9 @@ namespace cppcanvas
239 aParms );
242 + /* EMF+ */
243 + memset (aObjects, 0, sizeof (aObjects));
245 createActions( const_cast<GDIMetaFile&>(rMtf), // HACK(Q2):
246 // we're
247 // changing
248 --- cppcanvas/source/mtfrenderer/emfplus.cxx.old 1970-01-01 00:00:00.000000000 +0000
249 +++ cppcanvas/source/mtfrenderer/emfplus.cxx 2009-04-06 16:42:16.000000000 +0000
250 @@ -0,0 +1,1357 @@
251 +#include <tools/stream.hxx>
252 +#include <vcl/metaact.hxx>
253 +#include <svtools/filter.hxx>
254 +#include <basegfx/tools/canvastools.hxx>
255 +#include <basegfx/tools/tools.hxx>
256 +#include <basegfx/numeric/ftools.hxx>
257 +#include <basegfx/point/b2dpoint.hxx>
258 +#include <basegfx/vector/b2dsize.hxx>
259 +#include <basegfx/range/b2drange.hxx>
260 +#include <basegfx/range/b2drectangle.hxx>
261 +#include <basegfx/polygon/b2dpolygon.hxx>
262 +#include <basegfx/polygon/b2dpolypolygon.hxx>
263 +#include <basegfx/polygon/b2dpolypolygontools.hxx>
264 +#include <vcl/canvastools.hxx>
266 +#include <com/sun/star/rendering/XCanvas.hpp>
267 +#include <com/sun/star/rendering/TexturingMode.hpp>
268 +#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
270 +#include <bitmapaction.hxx>
271 +#include <implrenderer.hxx>
272 +#include <outdevstate.hxx>
273 +#include <polypolyaction.hxx>
275 +#define EmfPlusRecordTypeHeader 16385
276 +#define EmfPlusRecordTypeEndOfFile 16386
277 +#define EmfPlusRecordTypeGetDC 16388
278 +#define EmfPlusRecordTypeObject 16392
279 +#define EmfPlusRecordTypeFillRects 16394
280 +#define EmfPlusRecordTypeFillPolygon 16396
281 +#define EmfPlusRecordTypeDrawLines 16397
282 +#define EmfPlusRecordTypeFillPath 16404
283 +#define EmfPlusRecordTypeDrawPath 16405
284 +#define EmfPlusRecordTypeDrawImagePoints 16411
285 +#define EmfPlusRecordTypeDrawString 16412
286 +#define EmfPlusRecordTypeSetRenderingOrigin 16413
287 +#define EmfPlusRecordTypeSetAntiAliasMode 16414
288 +#define EmfPlusRecordTypeSetTextRenderingHint 16415
289 +#define EmfPlusRecordTypeSetInterpolationMode 16417
290 +#define EmfPlusRecordTypeSetPixelOffsetMode 16418
291 +#define EmfPlusRecordTypeSetCompositingQuality 16420
292 +#define EmfPlusRecordTypeSave 16421
293 +#define EmfPlusRecordTypeSetWorldTransform 16426
294 +#define EmfPlusRecordTypeResetWorldTransform 16427
295 +#define EmfPlusRecordTypeSetPageTransform 16432
296 +#define EmfPlusRecordTypeSetClipPath 16435
297 +#define EmfPlusRecordTypeSetClipRegion 16436
298 +#define EmfPlusRecordTypeDrawDriverString 16438
300 +#define EmfPlusObjectTypeBrush 0x100
301 +#define EmfPlusObjectTypePen 0x200
302 +#define EmfPlusObjectTypePath 0x300
303 +#define EmfPlusObjectTypeRegion 0x400
304 +#define EmfPlusObjectTypeImage 0x500
305 +#define EmfPlusObjectTypeFont 0x600
306 +#define EmfPlusObjectTypeStringFormat 0x700
307 +#define EmfPlusObjectTypeImageAttributes 0x800
309 +#define EmfPlusRegionInitialStateRectangle 0x10000000
310 +#define EmfPlusRegionInitialStatePath 0x10000001
311 +#define EmfPlusRegionInitialStateEmpty 0x10000002
312 +#define EmfPlusRegionInitialStateInfinite 0x10000003
314 +#define EMFP_DEBUG(x)
315 +//#define EMFP_DEBUG(x) x
317 +using namespace ::com::sun::star;
319 +namespace cppcanvas
321 + namespace internal
324 + EMFP_DEBUG (void dumpWords (SvStream& s, int i)
326 + sal_uInt32 pos = s.Tell ();
327 + INT16 data;
328 + for (; i > 0; i --) {
329 + s >> data;
330 + printf ("EMF+\tdata: %04hX\n", data);
332 + s.Seek (pos);
333 + });
335 + struct EMFPObject
337 + };
339 + struct EMFPPath : public EMFPObject
341 + ::basegfx::B2DPolyPolygon aPolygon;
342 + sal_Int32 nPoints;
343 + float* pPoints;
344 + sal_uInt8* pPointTypes;
346 + public:
347 + EMFPPath (sal_Int32 _nPoints, bool bLines = false)
349 + nPoints = _nPoints;
350 + pPoints = new float [nPoints*2];
351 + if (!bLines)
352 + pPointTypes = new sal_uInt8 [_nPoints];
353 + else
354 + pPointTypes = NULL;
357 + ~EMFPPath ()
359 + delete [] pPoints;
360 + delete [] pPointTypes;
363 + // TODO: remove rR argument when debug code is not longer needed
364 + void Read (SvStream& s, UINT32 pathFlags, ImplRenderer& rR)
366 + for (int i = 0; i < nPoints; i ++) {
367 + if (pathFlags & 0x4000) {
368 + // points are stored in short 16bit integer format
369 + UINT16 x, y;
371 + s >> x >> y;
372 + EMFP_DEBUG (printf ("EMF+\tpoint [x,y]: %hd,%hd\n", x, y));
373 + pPoints [i*2] = x;
374 + pPoints [i*2 + 1] = y;
375 + } else {
376 + // points are stored in Single (float) format
377 + s >> pPoints [i*2] >> pPoints [i*2 + 1];
378 + EMFP_DEBUG (printf ("EMF+\tpoint [x,y]: %f,%f\n", pPoints [i*2], pPoints [i*2 + 1]));
382 + if (pPointTypes)
383 + for (int i = 0; i < nPoints; i ++) {
384 + UINT8 pathType;
386 + s >> pPointTypes [i];
387 + EMFP_DEBUG (printf ("EMF+\tpoint type: %x\n", pPointTypes [i]));
390 + aPolygon.clear ();
392 + // debug code
393 + const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (GetPolygon (rR)));
394 + EMFP_DEBUG (printf ("EMF+\tpolygon bounding box: %f,%f %fx%f (mapped)\n", aBounds.getMinX (), aBounds.getMinY (), aBounds.getWidth (), aBounds.getHeight ()));
397 + ::basegfx::B2DPolyPolygon& GetPolygon (ImplRenderer& rR, bool bMapIt = true)
399 + ::basegfx::B2DPolygon polygon;
400 + sal_Int32 points = nPoints;
402 + aPolygon.clear ();
404 + int last_normal = 0, p = 0;
405 + ::basegfx::B2DPoint prev, mapped;
406 + bool hasPrev = false;
407 + for (int i = 0; i < nPoints; i ++) {
408 + if (p && pPointTypes && (pPointTypes [i] == 0)) {
409 + aPolygon.append (polygon);
410 + last_normal = i;
411 + p = 0;
412 + polygon.clear ();
415 + if (bMapIt)
416 + mapped = rR.Map (pPoints [i*2], pPoints [i*2 + 1]);
417 + else
418 + mapped = ::basegfx::B2DPoint (pPoints [i*2], pPoints [i*2 + 1]);
419 + //EMFP_DEBUG (printf ("polygon point: %f,%f mapped: %f,%f\n", pPoints [i*2], pPoints [i*2 + 1], mapped.getX (), mapped.getY ()));
420 + if (pPointTypes) {
421 + if ((pPointTypes [i] & 0x07) == 3) {
422 + if (((i - last_normal )% 3) == 1) {
423 + polygon.setNextControlPoint (p - 1, mapped);
424 + continue;
425 + } else if (((i - last_normal) % 3) == 2) {
426 + prev = mapped;
427 + hasPrev = true;
428 + continue;
430 + } else
431 + last_normal = i;
433 + polygon.append (mapped);
434 + if (hasPrev) {
435 + polygon.setPrevControlPoint (p, prev);
436 + hasPrev = false;
438 + p ++;
439 + if (pPointTypes && (pPointTypes [i] & 0x80)) { // closed polygon
440 + polygon.setClosed (true);
441 + aPolygon.append (polygon);
442 + last_normal = i + 1;
443 + p = 0;
444 + polygon.clear ();
448 + if (polygon.count ())
449 + aPolygon.append (polygon);
451 + return aPolygon;
453 + };
455 + struct EMFPRegion : public EMFPObject
457 + sal_Int32 parts;
458 + sal_Int32 *combineMode;
459 + sal_Int32 initialState;
460 + EMFPPath *initialPath;
461 + float ix, iy, iw, ih;
463 + EMFPRegion ()
465 + combineMode = NULL;
466 + initialPath = NULL;
469 + ~EMFPRegion ()
471 + if (combineMode) {
472 + delete [] combineMode;
473 + combineMode = NULL;
475 + if (initialPath) {
476 + delete initialPath;
477 + initialPath = NULL;
481 + void Read (SvStream& s)
483 + sal_uInt32 header;
485 + s >> header >> parts;
487 + EMFP_DEBUG (printf ("EMF+\tregion\n"));
488 + EMFP_DEBUG (printf ("EMF+\theader: 0x%08x parts: %d\n", header, parts));
490 + if (parts) {
491 + combineMode = new sal_Int32 [parts];
493 + for (int i = 0; i < parts; i ++) {
494 + s >> combineMode [i];
495 + EMFP_DEBUG (printf ("EMF+\tcombine mode [%d]: 0x%08x\n", i, combineMode [i]));
499 + s >> initialState;
500 + EMFP_DEBUG (printf ("EMF+\tinitial state: 0x%08x\n", initialState));
502 + };
504 + struct EMFPBrush : public EMFPObject
506 + ::Color solidColor;
507 + sal_uInt32 type;
508 + sal_uInt32 additionalFlags;
510 + /* linear gradient */
511 + sal_Int32 wrapMode;
512 + float areaX, areaY, areaWidth, areaHeight;
513 + ::Color secondColor; // first color is stored in solidColor;
514 + XForm transformation;
515 + bool hasTransformation;
516 + sal_Int32 blendPoints;
517 + float* blendPositions;
518 + float* blendFactors;
519 + sal_Int32 colorblendPoints;
520 + float* colorblendPositions;
521 + ::Color* colorblendColors;
522 + sal_Int32 surroundColorsNumber;
523 + ::Color* surroundColors;
524 + EMFPPath *path;
526 + public:
527 + EMFPBrush ()
529 + blendPositions = NULL;
530 + colorblendPositions = NULL;
531 + colorblendColors = NULL;
532 + surroundColors = NULL;
533 + path = NULL;
534 + hasTransformation = false;
537 + ~EMFPBrush ()
539 + if (blendPositions != NULL) {
540 + delete[] blendPositions;
541 + blendPositions = NULL;
543 + if (colorblendPositions != NULL) {
544 + delete[] colorblendPositions;
545 + colorblendPositions = NULL;
547 + if (colorblendColors != NULL) {
548 + delete[] colorblendColors;
549 + colorblendColors = NULL;
551 + if (surroundColors != NULL) {
552 + delete[] surroundColors;
553 + surroundColors = NULL;
555 + if (path) {
556 + delete path;
557 + path = NULL;
561 + UINT32 GetType () { return type; }
562 + const ::Color& GetColor () { return solidColor; }
564 + void Read (SvStream& s, ImplRenderer& rR)
566 + UINT32 header;
568 + s >> header >> type;
570 + EMFP_DEBUG (printf ("EMF+\tbrush\nEMF+\theader: 0x%08x type: %d\n", header, type));
572 + switch (type) {
573 + case 0:
575 + UINT32 color;
577 + s >> color;
578 + solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
579 + EMFP_DEBUG (printf ("EMF+\tsolid color: 0x%08x\n", color));
581 + break;
583 + // path gradient
584 + case 3:
586 + s >> additionalFlags >> wrapMode;
588 + EMFP_DEBUG (printf ("EMF+\tpath gradient, additional flags: 0x%02x\n", additionalFlags));
590 + UINT32 color;
592 + s >> color;
593 + solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
594 + EMFP_DEBUG (printf ("EMF+\tcenter color: 0x%08x\n", color));
596 + s >> areaX >> areaY;
597 + EMFP_DEBUG (printf ("EMF+\tcenter point: %f,%f\n", areaX, areaY));
599 + s >> surroundColorsNumber;
600 + EMFP_DEBUG (printf ("EMF+\tsurround colors: %d\n", surroundColorsNumber));
602 + surroundColors = new ::Color [surroundColorsNumber];
603 + for (int i = 0; i < surroundColorsNumber; i++) {
604 + s >> color;
605 + surroundColors[i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
606 + if (i == 0)
607 + secondColor = surroundColors [0];
608 + EMFP_DEBUG (printf ("EMF+\tsurround color[%d]: 0x%08x\n", i, color));
611 + if (additionalFlags & 0x01) {
612 + sal_Int32 pathLength;
614 + s >> pathLength;
615 + EMFP_DEBUG (printf ("EMF+\tpath length: %d\n", pathLength));
617 + sal_uInt32 pos = s.Tell ();
618 + EMFP_DEBUG (dumpWords (s, 32));
620 + sal_uInt32 pathHeader;
621 + sal_Int32 pathPoints, pathFlags;
622 + s >> pathHeader >> pathPoints >> pathFlags;
624 + EMFP_DEBUG (printf ("EMF+\tpath (brush path gradient)\n"));
625 + EMFP_DEBUG (printf ("EMF+\theader: 0x%08x points: %d additional flags: 0x%08x\n", pathHeader, pathPoints, pathFlags));
627 + path = new EMFPPath (pathPoints);
628 + path->Read (s, pathFlags, rR);
630 + s.Seek (pos + pathLength);
632 + const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (path->GetPolygon (rR, false)));
633 + areaWidth = aBounds.getWidth ();
634 + areaHeight = aBounds.getHeight ();
636 + EMFP_DEBUG (printf ("EMF+\tpolygon bounding box: %f,%f %fx%f\n", aBounds.getMinX (), aBounds.getMinY (), aBounds.getWidth (), aBounds.getHeight ()));
639 + if (additionalFlags & 0x02) {
640 + EMFP_DEBUG (printf ("EMF+\tuse transformation\n", color));
641 + s >> transformation;
642 + hasTransformation = true;
643 + EMFP_DEBUG (printf ("EMF+\tm11: %f m12: %f\nEMF+\tm21: %f m22: %f\nEMF+\tdx: %f dy: %f\n",
644 + transformation.eM11, transformation.eM12,
645 + transformation.eM21, transformation.eM22,
646 + transformation.eDx, transformation.eDy));
648 + if (additionalFlags & 0x08) {
649 + s >> blendPoints;
650 + EMFP_DEBUG (printf ("EMF+\tuse blend, points: %d\n", blendPoints));
651 + blendPositions = new float [2*blendPoints];
652 + blendFactors = blendPositions + blendPoints;
653 + for (int i=0; i < blendPoints; i ++) {
654 + s >> blendPositions [i];
655 + EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i, blendPositions [i]));
657 + for (int i=0; i < blendPoints; i ++) {
658 + s >> blendFactors [i];
659 + EMFP_DEBUG (printf ("EMF+\tfactor[%d]: %f\n", i, blendFactors [i]));
663 + if (additionalFlags & 0x04) {
664 + s >> colorblendPoints;
665 + EMFP_DEBUG (printf ("EMF+\tuse color blend, points: %d\n", colorblendPoints));
666 + colorblendPositions = new float [colorblendPoints];
667 + colorblendColors = new ::Color [colorblendPoints];
668 + for (int i=0; i < colorblendPoints; i ++) {
669 + s >> colorblendPositions [i];
670 + EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i, colorblendPositions [i]));
672 + for (int i=0; i < colorblendPoints; i ++) {
673 + s >> color;
674 + colorblendColors [i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
675 + EMFP_DEBUG (printf ("EMF+\tcolor[%d]: 0x%08x\n", i, color));
678 + } else
679 + EMFP_DEBUG (dumpWords (s, 1024));
681 + break;
683 + // linear gradient
684 + case 4:
686 + s >> additionalFlags >> wrapMode;
688 + EMFP_DEBUG (printf ("EMF+\tlinear gradient, additional flags: 0x%02x\n", additionalFlags));
690 + s >> areaX >> areaY >> areaWidth >> areaHeight;
692 + EMFP_DEBUG (printf ("EMF+\tarea: %f,%f - %fx%f\n", areaX, areaY, areaWidth, areaHeight));
694 + UINT32 color;
696 + s >> color;
697 + solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
698 + EMFP_DEBUG (printf ("EMF+\tfirst color: 0x%08x\n", color));
700 + s >> color;
701 + secondColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
702 + EMFP_DEBUG (printf ("EMF+\tsecond color: 0x%08x\n", color));
704 + // repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html
705 + s >> color;
706 + s >> color;
708 + if (additionalFlags & 0x02) {
709 + EMFP_DEBUG (printf ("EMF+\tuse transformation\n", color));
710 + s >> transformation;
711 + hasTransformation = true;
712 + EMFP_DEBUG (printf ("EMF+\tm11: %f m12: %f\nEMF+\tm21: %f m22: %f\nEMF+\tdx: %f dy: %f\n",
713 + transformation.eM11, transformation.eM12,
714 + transformation.eM21, transformation.eM22,
715 + transformation.eDx, transformation.eDy));
717 + if (additionalFlags & 0x08) {
718 + s >> blendPoints;
719 + EMFP_DEBUG (printf ("EMF+\tuse blend, points: %d\n", blendPoints));
720 + blendPositions = new float [2*blendPoints];
721 + blendFactors = blendPositions + blendPoints;
722 + for (int i=0; i < blendPoints; i ++) {
723 + s >> blendPositions [i];
724 + EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i, blendPositions [i]));
726 + for (int i=0; i < blendPoints; i ++) {
727 + s >> blendFactors [i];
728 + EMFP_DEBUG (printf ("EMF+\tfactor[%d]: %f\n", i, blendFactors [i]));
732 + if (additionalFlags & 0x04) {
733 + s >> colorblendPoints;
734 + EMFP_DEBUG (printf ("EMF+\tuse color blend, points: %d\n", colorblendPoints));
735 + colorblendPositions = new float [colorblendPoints];
736 + colorblendColors = new ::Color [colorblendPoints];
737 + for (int i=0; i < colorblendPoints; i ++) {
738 + s >> colorblendPositions [i];
739 + EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i, colorblendPositions [i]));
741 + for (int i=0; i < colorblendPoints; i ++) {
742 + s >> color;
743 + colorblendColors [i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
744 + EMFP_DEBUG (printf ("EMF+\tcolor[%d]: 0x%08x\n", i, color));
748 + break;
750 + default:
751 + EMFP_DEBUG (printf ("EMF+\tunhandled brush type: %d\n", type));
754 + };
756 + struct EMFPPen : public EMFPBrush
758 + XForm transformation;
759 + float width;
760 + sal_Int32 startCap;
761 + sal_Int32 endCap;
762 + sal_Int32 lineJoin;
763 + float mitterLimit;
764 + sal_Int32 dashStyle;
765 + sal_Int32 dashCap;
766 + float dashOffset;
767 + sal_Int32 dashPatternLen;
768 + float *dashPattern;
769 + sal_Int32 alignment;
770 + sal_Int32 compoundArrayLen;
771 + float *compoundArray;
772 + sal_Int32 customStartCapLen;
773 + sal_uInt8 *customStartCap;
774 + sal_Int32 customEndCapLen;
775 + sal_uInt8 *customEndCap;
777 + public:
778 + EMFPPen () : EMFPBrush ()
782 + void SetStrokeAttributes (rendering::StrokeAttributes& rStrokeAttributes, ImplRenderer& rR, const OutDevState& rState)
784 + rStrokeAttributes.StrokeWidth = (rState.mapModeTransform * rR.MapSize (width, 0)).getX ();
787 + void Read (SvStream& s, ImplRenderer& rR, sal_Int32 nHDPI, sal_Int32 nVDPI)
789 + UINT32 header, unknown, penFlags, unknown2;
790 + int i;
792 + s >> header >> unknown >> penFlags >> unknown2 >> width;
794 + EMFP_DEBUG (printf ("EMF+\tpen\nEMF+\theader: 0x%08x unknown: 0x%08x additional flags: 0x%08x unknown: 0x%08x width: %f\n", header, unknown, penFlags, unknown2, width));
796 + if (penFlags & 1)
797 + s >> transformation;
799 + if (penFlags & 2)
800 + s >> startCap;
801 + else
802 + startCap = 0;
804 + if (penFlags & 4)
805 + s >> endCap;
806 + else
807 + endCap = 0;
809 + if (penFlags & 8)
810 + s >> lineJoin;
811 + else
812 + lineJoin = 0;
814 + if (penFlags & 16)
815 + s >> mitterLimit;
816 + else
817 + mitterLimit = 0;
819 + if (penFlags & 32)
820 + s >> dashStyle;
821 + else
822 + dashStyle = 0;
824 + if (penFlags & 64)
825 + s >> dashCap;
826 + else
827 + dashCap = 0;
829 + if (penFlags & 128)
830 + s >> dashOffset;
831 + else
832 + dashOffset = 0;
834 + if (penFlags & 256) {
835 + s >> dashPatternLen;
836 + dashPattern = new float [dashPatternLen];
837 + for (i = 0; i < dashPatternLen; i++)
838 + s >> dashPattern [i];
839 + } else
840 + dashPatternLen = 0;
842 + if (penFlags & 512)
843 + s >> alignment;
844 + else
845 + alignment = 0;
847 + if (penFlags & 1024) {
848 + s >> compoundArrayLen;
849 + compoundArray = new float [compoundArrayLen];
850 + for (i = 0; i < compoundArrayLen; i++)
851 + s >> compoundArray [i];
852 + } else
853 + compoundArrayLen = 0;
855 + if (penFlags & 2048) {
856 + s >> customStartCapLen;
857 + customStartCap = new sal_uInt8 [customStartCapLen];
858 + for (i = 0; i < customStartCapLen; i++)
859 + s >> customStartCap [i];
860 + } else
861 + customStartCapLen = 0;
863 + if (penFlags & 4096) {
864 + s >> customEndCapLen;
865 + customEndCap = new sal_uInt8 [customEndCapLen];
866 + for (i = 0; i < customEndCapLen; i++)
867 + s >> customEndCap [i];
868 + } else
869 + customEndCapLen = 0;
871 + EMFPBrush::Read (s, rR);
873 + };
875 + struct EMFPImage : public EMFPObject
877 + sal_uInt32 type;
878 + sal_Int32 width;
879 + sal_Int32 height;
880 + sal_Int32 stride;
881 + sal_Int32 pixelFormat;
882 + Graphic graphic;
885 + void Read (SvStream &s)
887 + sal_uInt32 header, unknown;
889 + s >> header >> type;
891 + EMFP_DEBUG (printf ("EMF+\timage\nEMF+\theader: 0x%08x type: 0x%08x\n", header, type));
893 + if (type == 1) { // bitmap
894 + s >> width >> height >> stride >> pixelFormat >> unknown;
895 + EMFP_DEBUG (printf ("EMF+\tbitmap width: %d height: %d stride: %d pixelFormat: 0x%08x\n", width, height, stride, pixelFormat));
896 + if (width == 0) { // non native formats
897 + GraphicFilter filter;
899 + filter.ImportGraphic (graphic, String (), s);
900 + EMFP_DEBUG (printf ("EMF+\tbitmap width: %d height: %d\n", graphic.GetBitmap ().GetSizePixel ().Width (), graphic.GetBitmap ().GetSizePixel ().Height ()));
905 + };
907 + void ImplRenderer::ReadRectangle (SvStream& s, float& x, float& y, float &width, float& height, sal_uInt32 flags)
909 + if (flags & 0x4000) {
910 + sal_Int16 ix, iy, iw, ih;
912 + s >> ix >> iy >> iw >> ih;
914 + x = ix;
915 + y = iy;
916 + width = iw;
917 + height = ih;
918 + } else
919 + s >> x >> y >> width >> height;
922 + void ImplRenderer::ReadPoint (SvStream& s, float& x, float& y, sal_uInt32 flags)
924 + if (flags & 0x4000) {
925 + sal_Int16 ix, iy;
927 + s >> ix >> iy;
929 + x = ix;
930 + y = iy;
931 + } else
932 + s >> x >> y;
935 + void ImplRenderer::MapToDevice (double& x, double& y)
937 + // TODO: other untis
938 + x = 100*nMmX*x/nPixX;
939 + y = 100*nMmY*y/nPixY;
942 + ::basegfx::B2DPoint ImplRenderer::Map (::basegfx::B2DPoint& p)
944 + return Map (p.getX (), p.getY ());
947 + ::basegfx::B2DPoint ImplRenderer::Map (double ix, double iy)
949 + double x, y;
951 + x = ix*aWorldTransform.eM11 + iy*aWorldTransform.eM21 + aWorldTransform.eDx;
952 + y = ix*aWorldTransform.eM12 + iy*aWorldTransform.eM22 + aWorldTransform.eDy;
954 + MapToDevice (x, y);
956 + x -= nFrameLeft;
957 + y -= nFrameTop;
959 + x *= aBaseTransform.eM11;
960 + y *= aBaseTransform.eM22;
962 + return ::basegfx::B2DPoint (x, y);
965 + ::basegfx::B2DSize ImplRenderer::MapSize (double iwidth, double iheight)
967 + double w, h;
969 + w = iwidth*aWorldTransform.eM11 + iheight*aWorldTransform.eM21;
970 + h = iwidth*aWorldTransform.eM12 + iheight*aWorldTransform.eM22;
972 + MapToDevice (w, h);
974 + w *= aBaseTransform.eM11;
975 + h *= aBaseTransform.eM22;
977 + return ::basegfx::B2DSize (w, h);
980 + ::basegfx::B2DRange ImplRenderer::MapRectangle (double ix, double iy, double iwidth, double iheight)
982 + double x, y, w, h;
984 + x = ix*aWorldTransform.eM11 + iy*aWorldTransform.eM21 + aWorldTransform.eDx;
985 + y = ix*aWorldTransform.eM12 + iy*aWorldTransform.eM22 + aWorldTransform.eDy;
986 + w = iwidth*aWorldTransform.eM11 + iheight*aWorldTransform.eM21;
987 + h = iwidth*aWorldTransform.eM12 + iheight*aWorldTransform.eM22;
989 + MapToDevice (x, y);
990 + MapToDevice (w, h);
992 + x -= nFrameLeft;
993 + y -= nFrameTop;
995 + x *= aBaseTransform.eM11;
996 + y *= aBaseTransform.eM22;
997 + w *= aBaseTransform.eM11;
998 + h *= aBaseTransform.eM22;
1000 + return ::basegfx::B2DRange (x, y, x + w, y + h);
1003 + void ImplRenderer::EMFPPlusFillPolygon (::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms,
1004 + OutDevState& rState, const CanvasSharedPtr& rCanvas, bool isColor, sal_uInt32 brushIndexOrColor)
1006 + sal_uInt8 transparency;
1007 + ::basegfx::B2DPolyPolygon localPolygon (polygon);
1009 + EMFP_DEBUG (printf ("EMF+\tfill polygon\n"));
1011 + localPolygon.transform( rState.mapModeTransform );
1013 + ActionSharedPtr pPolyAction;
1015 + if (isColor) {
1016 + EMFP_DEBUG (printf ("EMF+\t\tcolor fill\n"));
1018 + transparency = 0xff - (brushIndexOrColor >> 24);
1020 + rState.isFillColorSet = true;
1021 + rState.isLineColorSet = false;
1022 + rState.fillColor = ::vcl::unotools::colorToDoubleSequence( ::Color (transparency,
1023 + (brushIndexOrColor >> 16) & 0xff,
1024 + (brushIndexOrColor >> 8) & 0xff,
1025 + brushIndexOrColor & 0xff),
1026 + rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace());
1028 + pPolyAction = ActionSharedPtr ( internal::PolyPolyActionFactory::createPolyPolyAction( localPolygon, rParms.mrCanvas, rState ) );
1030 + } else {
1031 + rState.isFillColorSet = true;
1032 + // extract UseBrush
1033 + EMFPBrush* brush = (EMFPBrush*) aObjects [brushIndexOrColor];
1034 + EMFP_DEBUG (printf ("EMF+\tbrush fill slot: %d (type: %d)\n", brushIndexOrColor, brush->GetType ()));
1036 + rState.isFillColorSet = false;
1037 + rState.isLineColorSet = false;
1039 + if (brush->type == 3 || brush->type == 4) {
1041 + if (brush->type == 3 && !(brush->additionalFlags & 0x1))
1042 + return; // we are unable to parse these brushes yet
1044 + ::basegfx::B2DHomMatrix aTextureTransformation;
1045 + ::basegfx::B2DHomMatrix aWorldTransformation;
1046 + ::basegfx::B2DHomMatrix aBaseTransformation;
1047 + rendering::Texture aTexture;
1048 + double nRotation( 0.0 );
1049 + const ::basegfx::B2DRectangle aBounds( ::basegfx::tools::getRange( localPolygon ) );
1050 + const double nScale( ::basegfx::pruneScaleValue( fabs( aBounds.getHeight()*sin(nRotation) ) +
1051 + fabs( aBounds.getWidth()*cos(nRotation) )));
1053 + aWorldTransformation.set (0, 0, aWorldTransform.eM11);
1054 + aWorldTransformation.set (0, 1, aWorldTransform.eM21);
1055 + aWorldTransformation.set (0, 2, aWorldTransform.eDx);
1056 + aWorldTransformation.set (1, 0, aWorldTransform.eM12);
1057 + aWorldTransformation.set (1, 1, aWorldTransform.eM22);
1058 + aWorldTransformation.set (1, 2, aWorldTransform.eDy);
1060 + aBaseTransformation.set (0, 0, aBaseTransform.eM11);
1061 + aBaseTransformation.set (0, 1, aBaseTransform.eM21);
1062 + aBaseTransformation.set (0, 2, aBaseTransform.eDx);
1063 + aBaseTransformation.set (1, 0, aBaseTransform.eM12);
1064 + aBaseTransformation.set (1, 1, aBaseTransform.eM22);
1065 + aBaseTransformation.set (1, 2, aBaseTransform.eDy);
1067 + if (brush->type == 4) {
1068 + aTextureTransformation.scale (brush->areaWidth, brush->areaHeight);
1069 + aTextureTransformation.translate (brush->areaX, brush->areaY);
1070 + } else {
1071 + aTextureTransformation.translate (-0.5, -0.5);
1072 + aTextureTransformation.scale (brush->areaWidth, brush->areaHeight);
1073 + aTextureTransformation.translate (brush->areaX,brush->areaY);
1076 + if (brush->hasTransformation) {
1077 + ::basegfx::B2DHomMatrix aTransformation;
1079 + aTransformation.set (0, 0, brush->transformation.eM11);
1080 + aTransformation.set (0, 1, brush->transformation.eM21);
1081 + aTransformation.set (0, 2, brush->transformation.eDx);
1082 + aTransformation.set (1, 0, brush->transformation.eM12);
1083 + aTransformation.set (1, 1, brush->transformation.eM22);
1084 + aTransformation.set (1, 2, brush->transformation.eDy);
1086 + aTextureTransformation *= aTransformation;
1089 + aTextureTransformation *= aWorldTransformation;
1090 + aTextureTransformation.scale (100.0*nMmX/nPixX, 100.0*nMmY/nPixY);
1091 + aTextureTransformation.translate (-nFrameLeft, -nFrameTop);
1092 + aTextureTransformation *= rState.mapModeTransform;
1093 + aTextureTransformation *= aBaseTransformation;
1095 + aTexture.RepeatModeX = rendering::TexturingMode::CLAMP;
1096 + aTexture.RepeatModeY = rendering::TexturingMode::CLAMP;
1097 + aTexture.Alpha = 1.0;
1099 + uno::Reference< rendering::XParametricPolyPolygon2DFactory > xFactory(
1100 + rParms.mrCanvas->getUNOCanvas()->getDevice()->getParametricPolyPolygonFactory() );
1102 + if( xFactory.is() ) {
1103 + const uno::Sequence< double > aStartColor(
1104 + ::vcl::unotools::colorToDoubleSequence( brush->solidColor,
1105 + rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() ) );
1106 + const uno::Sequence< double > aEndColor(
1107 + ::vcl::unotools::colorToDoubleSequence( brush->secondColor,
1108 + rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() ) );
1109 + uno::Sequence< uno::Sequence < double > > aColors (2);
1110 + uno::Sequence< double > aStops (2);
1112 + if (brush->blendPositions) {
1113 + EMFP_DEBUG (printf ("EMF+\t\tuse blend\n"));
1114 + aColors.realloc (brush->blendPoints);
1115 + aStops.realloc (brush->blendPoints);
1116 + int length = aStartColor.getLength ();
1117 + uno::Sequence< double > aColor (length);
1119 + OSL_ASSERT (length == aEndColor.getLength());
1121 + for (int i = 0; i < brush->blendPoints; i++) {
1122 + aStops[i] = brush->blendPositions [i];
1124 + for (int j = 0; j < length; j++) {
1125 + if (brush->type == 4) {
1126 +// // gamma correction
1127 +// if (brush->additionalFlags & 0x80)
1128 +// aColor [j] = pow (aStartColor [j]*(1 - brush->blendFactors[i]) + aEndColor [j]*brush->blendFactors[i], 1/2.2);
1129 +// else
1130 + aColor [j] = aStartColor [j]*(1 - brush->blendFactors[i]) + aEndColor [j]*brush->blendFactors[i];
1131 + } else
1132 + aColor [j] = aStartColor [j]*brush->blendFactors[i] + aEndColor [j]*(1 - brush->blendFactors[i]);
1135 + aColors[i] = aColor;
1137 + } else if (brush->colorblendPositions) {
1138 + EMFP_DEBUG (printf ("EMF+\t\tuse color blend\n"));
1139 + aColors.realloc (brush->colorblendPoints);
1140 + aStops.realloc (brush->colorblendPoints);
1142 + for (int i = 0; i < brush->colorblendPoints; i++) {
1143 + aStops[i] = brush->colorblendPositions [i];
1144 + aColors[(brush->type == 4) ? i : brush->colorblendPoints - 1 - i] = ::vcl::unotools::colorToDoubleSequence( brush->colorblendColors [i],
1145 + rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
1147 + } else {
1148 + aStops[0] = 0.0;
1149 + aStops[1] = 1.0;
1151 + if (brush->type == 4) {
1152 + aColors[0] = aStartColor;
1153 + aColors[1] = aEndColor;
1154 + } else {
1155 + aColors[1] = aStartColor;
1156 + aColors[0] = aEndColor;
1160 + EMFP_DEBUG (printf ("EMF+\t\tset gradient\n"));
1161 + if (brush->type == 4)
1162 + aTexture.Gradient = xFactory->createLinearHorizontalGradient( aColors,
1163 + aStops );
1164 + else {
1165 + geometry::RealRectangle2D aBoundsRectangle (0, 0, 1, 1);
1166 + aTexture.Gradient = xFactory->createEllipticalGradient( aColors,
1167 + aStops,
1168 + aBoundsRectangle);
1172 + ::basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform,
1173 + aTextureTransformation );
1175 + pPolyAction =
1176 + ActionSharedPtr ( internal::PolyPolyActionFactory::createPolyPolyAction( localPolygon,
1177 + rParms.mrCanvas,
1178 + rState,
1179 + aTexture ) );
1183 + if( pPolyAction )
1185 + EMFP_DEBUG (printf ("EMF+\t\tadd poly action\n"));
1187 + maActions.push_back(
1188 + MtfAction(
1189 + pPolyAction,
1190 + rParms.mrCurrActionIndex ) );
1192 + rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
1196 + void ImplRenderer::processEMFPlus( MetaCommentAction* pAct, const ActionFactoryParameters& rFactoryParms,
1197 + OutDevState& rState, const CanvasSharedPtr& rCanvas )
1199 + sal_uInt32 length = pAct->GetDataSize ();
1200 + SvMemoryStream rMF ((void*) pAct->GetData (), length, STREAM_READ);
1202 + length -= 4;
1204 + while (length > 0) {
1205 + UINT16 type, flags;
1206 + UINT32 size, dataSize;
1207 + sal_uInt32 next;
1209 + rMF >> type >> flags >> size >> dataSize;
1211 + next = rMF.Tell() + ( size - 12 );
1213 + EMFP_DEBUG (printf ("EMF+ record size: %d type: %04hx flags: %04hx data size: %d\n", size, type, flags, dataSize));
1215 + switch (type) {
1216 + case EmfPlusRecordTypeHeader:
1217 + UINT32 header, version;
1219 + rMF >> header >> version >> nHDPI >> nVDPI;
1221 + EMFP_DEBUG (printf ("EMF+ Header\n"));
1222 + EMFP_DEBUG (printf ("EMF+\theader: 0x%08x version: %d horizontal DPI: %d vertical DPI: %d dual: %d\n", header, version, nHDPI, nVDPI, flags & 1));
1224 + break;
1225 + case EmfPlusRecordTypeEndOfFile:
1226 + EMFP_DEBUG (printf ("EMF+ EndOfFile\n"));
1227 + break;
1228 + case EmfPlusRecordTypeGetDC:
1229 + EMFP_DEBUG (printf ("EMF+ GetDC\n"));
1230 + EMFP_DEBUG (printf ("EMF+\talready used in svtools wmf/emf filter parser\n"));
1231 + break;
1232 + case EmfPlusRecordTypeObject:
1234 + UINT32 objectLen;
1235 + sal_uInt32 index;
1237 + EMFP_DEBUG (printf ("EMF+ Object slot: %hd flags: %hx\n", flags & 0xff, flags & 0xff00));
1239 + index = flags & 0xff;
1240 + if (aObjects [index] != NULL) {
1241 + delete aObjects [index];
1242 + aObjects [index] = NULL;
1245 + switch (flags & 0xff00) {
1246 + case EmfPlusObjectTypeBrush:
1248 + EMFPBrush *brush;
1249 + aObjects [index] = brush = new EMFPBrush ();
1250 + brush->Read (rMF, *this);
1252 + break;
1254 + case EmfPlusObjectTypePen:
1256 + EMFPPen *pen;
1257 + aObjects [index] = pen = new EMFPPen ();
1258 + pen->Read (rMF, *this, nHDPI, nVDPI);
1260 + break;
1262 + case EmfPlusObjectTypePath:
1263 + sal_uInt32 header, pathFlags;
1264 + sal_Int32 points;
1266 + rMF >> header >> points >> pathFlags;
1268 + EMFP_DEBUG (printf ("EMF+\tpath\n"));
1269 + EMFP_DEBUG (printf ("EMF+\theader: 0x%08x points: %d additional flags: 0x%08x\n", header, points, pathFlags));
1271 + EMFPPath *path;
1272 + aObjects [index] = path = new EMFPPath (points);
1273 + path->Read (rMF, pathFlags, *this);
1275 + break;
1276 + case EmfPlusObjectTypeRegion: {
1277 + EMFPRegion *region;
1279 + aObjects [index] = region = new EMFPRegion ();
1280 + region->Read (rMF);
1282 + break;
1284 + case EmfPlusObjectTypeImage:
1286 + EMFPImage *image;
1287 + aObjects [index] = image = new EMFPImage ();
1288 + image->Read (rMF);
1290 + break;
1292 + default:
1293 + EMFP_DEBUG (printf ("EMF+\tObject unhandled flags: 0x%04x\n", flags & 0xff00));
1294 + break;
1297 + break;
1299 + case EmfPlusRecordTypeFillPath:
1301 + sal_uInt32 index = flags & 0xff;
1302 + sal_uInt32 brushIndexOrColor;
1304 + rMF >> brushIndexOrColor;
1306 + EMFP_DEBUG (printf ("EMF+ FillPath slot: %d\n", index));
1308 + EMFPPlusFillPolygon (((EMFPPath*) aObjects [index])->GetPolygon (*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
1310 + break;
1311 + case EmfPlusRecordTypeFillRects:
1313 + EMFP_DEBUG (printf ("EMF+ FillRects\n"));
1315 + sal_uInt32 brushIndexOrColor;
1316 + sal_Int32 rectangles;
1317 + ::basegfx::B2DPolygon polygon;
1319 + rMF >> brushIndexOrColor >> rectangles;
1321 + EMFP_DEBUG (printf ("EMF+\t%s: 0x%08x\n", (flags & 0x8000) ? "color" : "brush index", brushIndexOrColor));
1323 + for (int i=0; i < rectangles; i++) {
1324 + if (flags & 0x4000) {
1325 + /* 16bit integers */
1326 + sal_Int16 x, y, width, height;
1328 + rMF >> x >> y >> width >> height;
1330 + polygon.append (Map (x, y));
1331 + polygon.append (Map (x + width, y));
1332 + polygon.append (Map (x + width, y + height));
1333 + polygon.append (Map (x, y + height));
1335 + EMFP_DEBUG (printf ("EMF+\trectangle: %d,%d %dx%d\n", x, y, width, height));
1336 + } else {
1337 + /* Single's */
1338 + float x, y, width, height;
1340 + rMF >> x >> y >> width >> height;
1342 + polygon.append (Map (x, y));
1343 + polygon.append (Map (x + width, y));
1344 + polygon.append (Map (x + width, y + height));
1345 + polygon.append (Map (x, y + height));
1347 + EMFP_DEBUG (printf ("EMF+\trectangle: %f,%f %fx%f\n", x, y, width, height));
1350 + ::basegfx::B2DPolyPolygon polyPolygon (polygon);
1352 + EMFPPlusFillPolygon (polyPolygon, rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
1354 + break;
1356 + case EmfPlusRecordTypeFillPolygon:
1358 + sal_uInt8 index = flags & 0xff;
1359 + sal_uInt32 brushIndexOrColor;
1360 + sal_Int32 brushIndex;
1361 + sal_Int32 points;
1362 + UINT32 color;
1363 + USHORT transparency = 0;
1365 + rMF >> brushIndexOrColor;
1366 + rMF >> points;
1368 + EMFP_DEBUG (printf ("EMF+ FillPolygon in slot: %d points: %d\n", index, points));
1369 + EMFP_DEBUG (printf ("EMF+\twith solid color (ARGB): 0x%08X\n", color));
1371 + EMFPPath path (points, true);
1372 + path.Read (rMF, flags, *this);
1375 + EMFPPlusFillPolygon (path.GetPolygon (*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
1377 + break;
1379 + case EmfPlusRecordTypeDrawLines:
1381 + sal_uInt32 index = flags & 0xff;
1382 + sal_uInt32 points;
1384 + rMF >> points;
1386 + EMFP_DEBUG (printf ("EMF+ DrawLines in slot: %d points: %d\n", index, points));
1388 + EMFPPath path (points, true);
1389 + path.Read (rMF, flags, *this);
1391 + EMFPPen* pen = (EMFPPen*) aObjects [index];
1393 + rState.isFillColorSet = false;
1394 + rState.isLineColorSet = true;
1395 + rState.lineColor = ::vcl::unotools::colorToDoubleSequence (pen->GetColor (),
1396 + rCanvas->getUNOCanvas ()->getDevice()->getDeviceColorSpace() );
1397 + ::basegfx::B2DPolyPolygon& polygon (path.GetPolygon (*this));
1399 + polygon.transform( rState.mapModeTransform );
1401 + rendering::StrokeAttributes aStrokeAttributes;
1403 + pen->SetStrokeAttributes (aStrokeAttributes, *this, rState);
1405 + ActionSharedPtr pPolyAction(
1406 + internal::PolyPolyActionFactory::createPolyPolyAction(
1407 + polygon, rFactoryParms.mrCanvas, rState, aStrokeAttributes ) );
1409 + if( pPolyAction )
1411 + maActions.push_back(
1412 + MtfAction(
1413 + pPolyAction,
1414 + rFactoryParms.mrCurrActionIndex ) );
1416 + rFactoryParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
1419 + break;
1421 + case EmfPlusRecordTypeDrawPath:
1423 + UINT32 penIndex;
1425 + rMF >> penIndex;
1427 + EMFP_DEBUG (printf ("EMF+ DrawPath\n"));
1428 + EMFP_DEBUG (printf ("EMF+\tpen: %d\n", penIndex));
1430 + EMFPPath* path = (EMFPPath*) aObjects [flags & 0xff];
1431 + EMFPPen* pen = (EMFPPen*) aObjects [penIndex];
1433 + rState.isFillColorSet = false;
1434 + rState.isLineColorSet = true;
1435 + rState.lineColor = ::vcl::unotools::colorToDoubleSequence (pen->GetColor (),
1436 + rCanvas->getUNOCanvas ()->getDevice()->getDeviceColorSpace());
1437 + ::basegfx::B2DPolyPolygon& polygon (path->GetPolygon (*this));
1439 + polygon.transform( rState.mapModeTransform );
1440 + rendering::StrokeAttributes aStrokeAttributes;
1442 + pen->SetStrokeAttributes (aStrokeAttributes, *this, rState);
1444 + ActionSharedPtr pPolyAction(
1445 + internal::PolyPolyActionFactory::createPolyPolyAction(
1446 + polygon, rFactoryParms.mrCanvas, rState, aStrokeAttributes ) );
1448 + if( pPolyAction )
1450 + maActions.push_back(
1451 + MtfAction(
1452 + pPolyAction,
1453 + rFactoryParms.mrCurrActionIndex ) );
1455 + rFactoryParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
1457 + break;
1459 + case EmfPlusRecordTypeDrawImagePoints:
1461 + sal_uInt32 attrIndex;
1462 + sal_Int32 sourceUnit;
1464 + rMF >> attrIndex >> sourceUnit;
1466 + EMFP_DEBUG (printf ("EMF+ DrawImagePoints attributes index: %d source unit: %d\n", attrIndex, sourceUnit));
1467 + EMFP_DEBUG (printf ("EMF+\tTODO: use image attributes\n"));
1469 + if (sourceUnit == 2 && aObjects [flags & 0xff]) { // we handle only GraphicsUnit.Pixel now
1470 + EMFPImage& image = *(EMFPImage *) aObjects [flags & 0xff];
1471 + float sx, sy, sw, sh;
1472 + sal_Int32 unknown;
1474 + ReadRectangle (rMF, sx, sy, sw, sh);
1476 + rMF >> unknown;
1478 + EMFP_DEBUG (printf ("EMF+ DrawImagePoints source rectangle: %f,%f %fx%f unknown: 0x%08x\n", sx, sy, sw, sh, unknown));
1480 + if (unknown == 3) { // it probably means number of points defining destination rectangle
1481 + float x1, y1, x2, y2, x3, y3;
1483 + ReadPoint (rMF, x1, y1);
1484 + ReadPoint (rMF, x2, y2);
1485 + ReadPoint (rMF, x3, y3);
1487 + BitmapEx aBmp( image.graphic.GetBitmapEx () );
1488 + const Rectangle aCropRect (::vcl::unotools::pointFromB2DPoint (Map (sx, sy)),
1489 + ::vcl::unotools::sizeFromB2DSize (MapSize(sw, sh)));
1490 + aBmp.Crop( aCropRect );
1493 + ActionSharedPtr pBmpAction (
1494 + internal::BitmapActionFactory::createBitmapAction (
1495 + aBmp,
1496 + rState.mapModeTransform * Map (x1, y1),
1497 + rState.mapModeTransform * MapSize(x2 - x1, y3 - y1),
1498 + rCanvas,
1499 + rState));
1501 + if( pBmpAction ) {
1502 + maActions.push_back( MtfAction( pBmpAction,
1503 + rFactoryParms.mrCurrActionIndex ) );
1505 + rFactoryParms.mrCurrActionIndex += pBmpAction->getActionCount()-1;
1507 + } else
1508 + EMFP_DEBUG (printf ("EMF+ DrawImagePoints TODO (fixme)\n"));
1510 + break;
1512 + case EmfPlusRecordTypeDrawString:
1513 + EMFP_DEBUG (printf ("EMF+ DrawString\n"));
1514 + EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1515 + break;
1516 + case EmfPlusRecordTypeSetPageTransform:
1517 + rMF >> fPageScale;
1519 + EMFP_DEBUG (printf ("EMF+ SetPageTransform\n"));
1520 + EMFP_DEBUG (printf ("EMF+\tscale: %f unit: %d\n", fPageScale, flags));
1521 + EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1522 + break;
1523 + case EmfPlusRecordTypeSetRenderingOrigin:
1524 + rMF >> nOriginX >> nOriginY;
1525 + EMFP_DEBUG (printf ("EMF+ SetRenderingOrigin\n"));
1526 + EMFP_DEBUG (printf ("EMF+\torigin [x,y]: %d,%d\n", nOriginX, nOriginY));
1527 + break;
1528 + case EmfPlusRecordTypeSetTextRenderingHint:
1529 + EMFP_DEBUG (printf ("EMF+ SetTextRenderingHint\n"));
1530 + EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1531 + break;
1532 + case EmfPlusRecordTypeSetAntiAliasMode:
1533 + EMFP_DEBUG (printf ("EMF+ SetAntiAliasMode\n"));
1534 + EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1535 + break;
1536 + case EmfPlusRecordTypeSetInterpolationMode:
1537 + EMFP_DEBUG (printf ("EMF+ InterpolationMode\n"));
1538 + EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1539 + break;
1540 + case EmfPlusRecordTypeSetPixelOffsetMode:
1541 + EMFP_DEBUG (printf ("EMF+ SetPixelOffsetMode\n"));
1542 + EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1543 + break;
1544 + case EmfPlusRecordTypeSetCompositingQuality:
1545 + EMFP_DEBUG (printf ("EMF+ SetCompositingQuality\n"));
1546 + EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1547 + break;
1548 + case EmfPlusRecordTypeSave:
1549 + EMFP_DEBUG (printf ("EMF+ Save\n"));
1550 + EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1551 + break;
1552 + case EmfPlusRecordTypeSetWorldTransform: {
1553 + EMFP_DEBUG (printf ("EMF+ SetWorldTransform\n"));
1554 + XForm transform;
1555 + rMF >> transform;
1556 + aWorldTransform.Set (transform);
1557 + EMFP_DEBUG (printf ("EMF+\tm11: %f m12: %f\nEMF+\tm21: %f m22: %f\nEMF+\tdx: %f dy: %f\n",
1558 + aWorldTransform.eM11, aWorldTransform.eM12,
1559 + aWorldTransform.eM21, aWorldTransform.eM22,
1560 + aWorldTransform.eDx, aWorldTransform.eDy));
1561 + break;
1563 + case EmfPlusRecordTypeResetWorldTransform:
1564 + EMFP_DEBUG (printf ("EMF+ ResetWorldTransform\n"));
1565 + aWorldTransform.SetIdentity ();
1566 + break;
1567 + case EmfPlusRecordTypeSetClipPath:
1569 + EMFP_DEBUG (printf ("EMF+ SetClipPath\n"));
1570 + EMFP_DEBUG (printf ("EMF+\tpath in slot: %d\n", flags & 0xff));
1572 + EMFPPath& path = *(EMFPPath*) aObjects [flags & 0xff];
1573 + ::basegfx::B2DPolyPolygon& clipPoly (path.GetPolygon (*this));
1575 + clipPoly.transform (rState.mapModeTransform);
1576 + updateClipping (clipPoly, rFactoryParms, false);
1578 + break;
1580 + case EmfPlusRecordTypeSetClipRegion: {
1581 + EMFP_DEBUG (printf ("EMF+ SetClipRegion\n"));
1582 + EMFP_DEBUG (printf ("EMF+\tregion in slot: %d combine mode: %d\n", flags & 0xff, (flags & 0xff00) >> 8));
1583 + EMFPRegion& region = *(EMFPRegion*) aObjects [flags & 0xff];
1585 + // reset clip
1586 + if (region.parts == 0 && region.initialState == EmfPlusRegionInitialStateInfinite) {
1587 + updateClipping (::basegfx::B2DPolyPolygon (), rFactoryParms, false);
1588 + } else
1589 + EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1590 + break;
1592 + case EmfPlusRecordTypeDrawDriverString:
1593 + EMFP_DEBUG (printf ("EMF+ DrawDriverString, flags: 0x%04x\n", flags));
1594 + EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1595 + break;
1596 + default:
1597 + EMFP_DEBUG (printf ("EMF+ unhandled record type: %d\n", type));
1598 + EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1601 + rMF.Seek (next);
1603 + length -= size;