1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2010 Novell, Inc.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <tools/stream.hxx>
30 #include <vcl/metaact.hxx>
31 #include <vcl/graphicfilter.hxx>
32 #include <basegfx/tools/canvastools.hxx>
33 #include <basegfx/tools/gradienttools.hxx>
34 #include <basegfx/tools/tools.hxx>
35 #include <basegfx/numeric/ftools.hxx>
36 #include <basegfx/point/b2dpoint.hxx>
37 #include <basegfx/vector/b2dsize.hxx>
38 #include <basegfx/range/b2drange.hxx>
39 #include <basegfx/range/b2drectangle.hxx>
40 #include <basegfx/polygon/b2dpolygon.hxx>
41 #include <basegfx/polygon/b2dpolygontools.hxx>
42 #include <basegfx/polygon/b2dpolypolygon.hxx>
43 #include <basegfx/polygon/b2dpolypolygontools.hxx>
44 #include <vcl/canvastools.hxx>
45 #include <rtl/ustring.hxx>
46 #include <sal/alloca.h>
48 #include <com/sun/star/rendering/XCanvas.hpp>
49 #include <com/sun/star/rendering/TexturingMode.hpp>
51 #include <bitmapaction.hxx>
52 #include <implrenderer.hxx>
53 #include <outdevstate.hxx>
54 #include <polypolyaction.hxx>
55 #include <textaction.hxx>
58 #define EmfPlusRecordTypeHeader 16385
59 #define EmfPlusRecordTypeEndOfFile 16386
60 #define EmfPlusRecordTypeGetDC 16388
61 #define EmfPlusRecordTypeObject 16392
62 #define EmfPlusRecordTypeFillRects 16394
63 #define EmfPlusRecordTypeFillPolygon 16396
64 #define EmfPlusRecordTypeDrawLines 16397
65 #define EmfPlusRecordTypeFillPie 16400
66 #define EmfPlusRecordTypeFillPath 16404
67 #define EmfPlusRecordTypeDrawPath 16405
68 #define EmfPlusRecordTypeDrawImagePoints 16411
69 #define EmfPlusRecordTypeDrawString 16412
70 #define EmfPlusRecordTypeSetRenderingOrigin 16413
71 #define EmfPlusRecordTypeSetAntiAliasMode 16414
72 #define EmfPlusRecordTypeSetTextRenderingHint 16415
73 #define EmfPlusRecordTypeSetInterpolationMode 16417
74 #define EmfPlusRecordTypeSetPixelOffsetMode 16418
75 #define EmfPlusRecordTypeSetCompositingQuality 16420
76 #define EmfPlusRecordTypeSave 16421
77 #define EmfPlusRecordTypeSetWorldTransform 16426
78 #define EmfPlusRecordTypeResetWorldTransform 16427
79 #define EmfPlusRecordTypeMultiplyWorldTransform 16428
80 #define EmfPlusRecordTypeSetPageTransform 16432
81 #define EmfPlusRecordTypeSetClipPath 16435
82 #define EmfPlusRecordTypeSetClipRegion 16436
83 #define EmfPlusRecordTypeDrawDriverString 16438
85 #define EmfPlusObjectTypeBrush 0x100
86 #define EmfPlusObjectTypePen 0x200
87 #define EmfPlusObjectTypePath 0x300
88 #define EmfPlusObjectTypeRegion 0x400
89 #define EmfPlusObjectTypeImage 0x500
90 #define EmfPlusObjectTypeFont 0x600
91 #define EmfPlusObjectTypeStringFormat 0x700
92 #define EmfPlusObjectTypeImageAttributes 0x800
94 #define EmfPlusRegionInitialStateRectangle 0x10000000
95 #define EmfPlusRegionInitialStatePath 0x10000001
96 #define EmfPlusRegionInitialStateEmpty 0x10000002
97 #define EmfPlusRegionInitialStateInfinite 0x10000003
99 #if OSL_DEBUG_LEVEL > 1
100 #define EMFP_DEBUG(x) x
102 #define EMFP_DEBUG(x)
105 using namespace ::com::sun::star
;
106 using namespace ::basegfx
;
113 EMFP_DEBUG (void dumpWords (SvStream
& s
, int i
)
115 sal_uInt32 pos
= s
.Tell ();
117 for (; i
> 0; i
--) {
119 printf ("EMF+\tdata: %04hX\n", data
);
126 virtual ~EMFPObject() {}
129 struct EMFPPath
: public EMFPObject
131 ::basegfx::B2DPolyPolygon aPolygon
;
134 sal_uInt8
* pPointTypes
;
137 EMFPPath (sal_Int32 _nPoints
, bool bLines
= false)
139 if( _nPoints
<0 || sal_uInt32(_nPoints
)>SAL_MAX_INT32
/(2*sizeof(float)) )
140 _nPoints
= SAL_MAX_INT32
/(2*sizeof(float));
142 pPoints
= new float [nPoints
*2];
144 pPointTypes
= new sal_uInt8
[_nPoints
];
152 delete [] pPointTypes
;
155 // TODO: remove rR argument when debug code is not longer needed
156 void Read (SvStream
& s
, sal_uInt32 pathFlags
, ImplRenderer
& rR
)
158 for (int i
= 0; i
< nPoints
; i
++) {
159 if (pathFlags
& 0x4000) {
160 // points are stored in short 16bit integer format
164 EMFP_DEBUG (printf ("EMF+\tpoint [x,y]: %hd,%hd\n", x
, y
));
166 pPoints
[i
*2 + 1] = y
;
168 // points are stored in Single (float) format
169 s
>> pPoints
[i
*2] >> pPoints
[i
*2 + 1];
170 EMFP_DEBUG (printf ("EMF+\tpoint [x,y]: %f,%f\n", pPoints
[i
*2], pPoints
[i
*2 + 1]));
175 for (int i
= 0; i
< nPoints
; i
++) {
176 s
>> pPointTypes
[i
];
177 EMFP_DEBUG (printf ("EMF+\tpoint type: %x\n", pPointTypes
[i
]));
183 const ::basegfx::B2DRectangle
aBounds (::basegfx::tools::getRange (GetPolygon (rR
)));
184 EMFP_DEBUG (printf ("EMF+\tpolygon bounding box: %f,%f %fx%f (mapped)\n", aBounds
.getMinX (), aBounds
.getMinY (), aBounds
.getWidth (), aBounds
.getHeight ()));
187 ::basegfx::B2DPolyPolygon
& GetPolygon (ImplRenderer
& rR
, bool bMapIt
= true)
189 ::basegfx::B2DPolygon polygon
;
193 int last_normal
= 0, p
= 0;
194 ::basegfx::B2DPoint prev
, mapped
;
195 bool hasPrev
= false;
196 for (int i
= 0; i
< nPoints
; i
++) {
197 if (p
&& pPointTypes
&& (pPointTypes
[i
] == 0)) {
198 aPolygon
.append (polygon
);
205 mapped
= rR
.Map (pPoints
[i
*2], pPoints
[i
*2 + 1]);
207 mapped
= ::basegfx::B2DPoint (pPoints
[i
*2], pPoints
[i
*2 + 1]);
208 //EMFP_DEBUG (printf ("polygon point: %f,%f mapped: %f,%f\n", pPoints [i*2], pPoints [i*2 + 1], mapped.getX (), mapped.getY ()));
210 if ((pPointTypes
[i
] & 0x07) == 3) {
211 if (((i
- last_normal
)% 3) == 1) {
212 polygon
.setNextControlPoint (p
- 1, mapped
);
213 EMFP_DEBUG (printf ("polygon append next: %d mapped: %f,%f\n", p
- 1, mapped
.getX (), mapped
.getY ()));
215 } else if (((i
- last_normal
) % 3) == 2) {
223 polygon
.append (mapped
);
224 EMFP_DEBUG (printf ("polygon append point: %f,%f mapped: %f,%f\n", pPoints
[i
*2], pPoints
[i
*2 + 1], mapped
.getX (), mapped
.getY ()));
226 polygon
.setPrevControlPoint (p
, prev
);
227 EMFP_DEBUG (printf ("polygon append prev: %d mapped: %f,%f\n", p
, prev
.getX (), prev
.getY ()));
231 if (pPointTypes
&& (pPointTypes
[i
] & 0x80)) { // closed polygon
232 polygon
.setClosed (true);
233 aPolygon
.append (polygon
);
234 EMFP_DEBUG (printf ("close polygon\n"));
241 if (polygon
.count ())
242 aPolygon
.append (polygon
);
245 for (unsigned int i
=0; i
<aPolygon
.count(); i
++) {
246 polygon
= aPolygon
.getB2DPolygon(i
);
247 printf ("polygon: %d\n", i
);
248 for (unsigned int j
=0; j
<polygon
.count(); j
++) {
249 ::basegfx::B2DPoint point
= polygon
.getB2DPoint(j
);
250 printf ("point: %f,%f\n", point
.getX(), point
.getY());
251 if (polygon
.isPrevControlPointUsed(j
)) {
252 point
= polygon
.getPrevControlPoint(j
);
253 printf ("prev: %f,%f\n", point
.getX(), point
.getY());
255 if (polygon
.isNextControlPointUsed(j
)) {
256 point
= polygon
.getNextControlPoint(j
);
257 printf ("next: %f,%f\n", point
.getX(), point
.getY());
267 struct EMFPRegion
: public EMFPObject
270 sal_Int32
*combineMode
;
271 sal_Int32 initialState
;
272 EMFPPath
*initialPath
;
273 float ix
, iy
, iw
, ih
;
284 delete [] combineMode
;
293 void Read (SvStream
& s
)
297 s
>> header
>> parts
;
299 EMFP_DEBUG (printf ("EMF+\tregion\n"));
300 EMFP_DEBUG (printf ("EMF+\theader: 0x%08x parts: %d\n", (unsigned int)header
, (int)parts
));
303 if( parts
<0 || sal_uInt32(parts
)>SAL_MAX_INT32
/sizeof(sal_Int32
) )
304 parts
= SAL_MAX_INT32
/sizeof(sal_Int32
);
306 combineMode
= new sal_Int32
[parts
];
308 for (int i
= 0; i
< parts
; i
++) {
309 s
>> combineMode
[i
];
310 EMFP_DEBUG (printf ("EMF+\tcombine mode [%d]: 0x%08x\n", i
,(unsigned int)combineMode
[i
]));
315 EMFP_DEBUG (printf ("EMF+\tinitial state: 0x%d\n",(int) initialState
));
319 struct EMFPBrush
: public EMFPObject
323 sal_uInt32 additionalFlags
;
325 /* linear gradient */
327 float areaX
, areaY
, areaWidth
, areaHeight
;
328 ::Color secondColor
; // first color is stored in solidColor;
329 XForm transformation
;
330 bool hasTransformation
;
331 sal_Int32 blendPoints
;
332 float* blendPositions
;
334 sal_Int32 colorblendPoints
;
335 float* colorblendPositions
;
336 ::Color
* colorblendColors
;
337 sal_Int32 surroundColorsNumber
;
338 ::Color
* surroundColors
;
344 blendPositions
= NULL
;
345 colorblendPositions
= NULL
;
346 colorblendColors
= NULL
;
347 surroundColors
= NULL
;
349 hasTransformation
= false;
354 if (blendPositions
!= NULL
) {
355 delete[] blendPositions
;
356 blendPositions
= NULL
;
358 if (colorblendPositions
!= NULL
) {
359 delete[] colorblendPositions
;
360 colorblendPositions
= NULL
;
362 if (colorblendColors
!= NULL
) {
363 delete[] colorblendColors
;
364 colorblendColors
= NULL
;
366 if (surroundColors
!= NULL
) {
367 delete[] surroundColors
;
368 surroundColors
= NULL
;
376 sal_uInt32
GetType() const { return type
; }
377 const ::Color
& GetColor() const { return solidColor
; }
379 void Read (SvStream
& s
, ImplRenderer
& rR
)
385 EMFP_DEBUG (printf ("EMF+\tbrush\nEMF+\theader: 0x%08x type: %d\n",(unsigned int) header
,(int) type
));
393 solidColor
= ::Color (0xff - (color
>> 24), (color
>> 16) & 0xff, (color
>> 8) & 0xff, color
& 0xff);
394 EMFP_DEBUG (printf ("EMF+\tsolid color: 0x%08x\n", (unsigned int)color
));
401 s
>> additionalFlags
>> wrapMode
;
403 EMFP_DEBUG (printf ("EMF+\tpath gradient, additional flags: 0x%02x\n",(unsigned int) additionalFlags
));
408 solidColor
= ::Color (0xff - (color
>> 24), (color
>> 16) & 0xff, (color
>> 8) & 0xff, color
& 0xff);
409 EMFP_DEBUG (printf ("EMF+\tcenter color: 0x%08x\n",(unsigned int) color
));
412 EMFP_DEBUG (printf ("EMF+\tcenter point: %f,%f\n", areaX
, areaY
));
414 s
>> surroundColorsNumber
;
415 EMFP_DEBUG (printf ("EMF+\tsurround colors: %d\n",(int) surroundColorsNumber
));
417 if( surroundColorsNumber
<0 || sal_uInt32(surroundColorsNumber
)>SAL_MAX_INT32
/sizeof(::Color
) )
418 surroundColorsNumber
= SAL_MAX_INT32
/sizeof(::Color
);
420 surroundColors
= new ::Color
[surroundColorsNumber
];
421 for (int i
= 0; i
< surroundColorsNumber
; i
++) {
423 surroundColors
[i
] = ::Color (0xff - (color
>> 24), (color
>> 16) & 0xff, (color
>> 8) & 0xff, color
& 0xff);
425 secondColor
= surroundColors
[0];
426 EMFP_DEBUG (printf ("EMF+\tsurround color[%d]: 0x%08x\n", i
, (unsigned int)color
));
429 if (additionalFlags
& 0x01) {
430 sal_Int32 pathLength
;
433 EMFP_DEBUG (printf ("EMF+\tpath length: %d\n", (int)pathLength
));
435 sal_uInt32 pos
= s
.Tell ();
436 EMFP_DEBUG (dumpWords (s
, 32));
438 sal_uInt32 pathHeader
;
439 sal_Int32 pathPoints
, pathFlags
;
440 s
>> pathHeader
>> pathPoints
>> pathFlags
;
442 EMFP_DEBUG (printf ("EMF+\tpath (brush path gradient)\n"));
443 EMFP_DEBUG (printf ("EMF+\theader: 0x%08x points: %d additional flags: 0x%d\n", (unsigned int)pathHeader
, (int)pathPoints
, (int)pathFlags
));
445 path
= new EMFPPath (pathPoints
);
446 path
->Read (s
, pathFlags
, rR
);
448 s
.Seek (pos
+ pathLength
);
450 const ::basegfx::B2DRectangle
aBounds (::basegfx::tools::getRange (path
->GetPolygon (rR
, false)));
451 areaWidth
= aBounds
.getWidth ();
452 areaHeight
= aBounds
.getHeight ();
454 EMFP_DEBUG (printf ("EMF+\tpolygon bounding box: %f,%f %fx%f\n", aBounds
.getMinX (), aBounds
.getMinY (), aBounds
.getWidth (), aBounds
.getHeight ()));
457 if (additionalFlags
& 0x02) {
458 EMFP_DEBUG (printf ("EMF+\tuse transformation\n"));
460 hasTransformation
= true;
461 EMFP_DEBUG (printf ("EMF+\tm11: %f m12: %f\nEMF+\tm21: %f m22: %f\nEMF+\tdx: %f dy: %f\n",
462 transformation
.eM11
, transformation
.eM12
,
463 transformation
.eM21
, transformation
.eM22
,
464 transformation
.eDx
, transformation
.eDy
));
466 if (additionalFlags
& 0x08) {
468 EMFP_DEBUG (printf ("EMF+\tuse blend, points: %d\n", (int)blendPoints
));
469 if( blendPoints
<0 || sal_uInt32(blendPoints
)>SAL_MAX_INT32
/(2*sizeof(float)) )
470 blendPoints
= SAL_MAX_INT32
/(2*sizeof(float));
471 blendPositions
= new float [2*blendPoints
];
472 blendFactors
= blendPositions
+ blendPoints
;
473 for (int i
=0; i
< blendPoints
; i
++) {
474 s
>> blendPositions
[i
];
475 EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i
, blendPositions
[i
]));
477 for (int i
=0; i
< blendPoints
; i
++) {
478 s
>> blendFactors
[i
];
479 EMFP_DEBUG (printf ("EMF+\tfactor[%d]: %f\n", i
, blendFactors
[i
]));
483 if (additionalFlags
& 0x04) {
484 s
>> colorblendPoints
;
485 EMFP_DEBUG (printf ("EMF+\tuse color blend, points: %d\n", (int)colorblendPoints
));
486 if( colorblendPoints
<0 || sal_uInt32(colorblendPoints
)>SAL_MAX_INT32
/sizeof(float) )
487 colorblendPoints
= SAL_MAX_INT32
/sizeof(float);
488 if( sal_uInt32(colorblendPoints
)>SAL_MAX_INT32
/sizeof(::Color
) )
489 colorblendPoints
= SAL_MAX_INT32
/sizeof(::Color
);
490 colorblendPositions
= new float [colorblendPoints
];
491 colorblendColors
= new ::Color
[colorblendPoints
];
492 for (int i
=0; i
< colorblendPoints
; i
++) {
493 s
>> colorblendPositions
[i
];
494 EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i
, colorblendPositions
[i
]));
496 for (int i
=0; i
< colorblendPoints
; i
++) {
498 colorblendColors
[i
] = ::Color (0xff - (color
>> 24), (color
>> 16) & 0xff, (color
>> 8) & 0xff, color
& 0xff);
499 EMFP_DEBUG (printf ("EMF+\tcolor[%d]: 0x%08x\n", i
,(unsigned int) color
));
503 EMFP_DEBUG (dumpWords (s
, 1024));
510 s
>> additionalFlags
>> wrapMode
;
512 EMFP_DEBUG (printf ("EMF+\tlinear gradient, additional flags: 0x%02x\n", (unsigned int)additionalFlags
));
514 s
>> areaX
>> areaY
>> areaWidth
>> areaHeight
;
516 EMFP_DEBUG (printf ("EMF+\tarea: %f,%f - %fx%f\n", areaX
, areaY
, areaWidth
, areaHeight
));
521 solidColor
= ::Color (0xff - (color
>> 24), (color
>> 16) & 0xff, (color
>> 8) & 0xff, color
& 0xff);
522 EMFP_DEBUG (printf ("EMF+\tfirst color: 0x%08x\n", color
));
525 secondColor
= ::Color (0xff - (color
>> 24), (color
>> 16) & 0xff, (color
>> 8) & 0xff, color
& 0xff);
526 EMFP_DEBUG (printf ("EMF+\tsecond color: 0x%08x\n", color
));
528 // repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html
532 if (additionalFlags
& 0x02) {
533 EMFP_DEBUG (printf ("EMF+\tuse transformation\n"));
535 hasTransformation
= true;
536 EMFP_DEBUG (printf ("EMF+\tm11: %f m12: %f\nEMF+\tm21: %f m22: %f\nEMF+\tdx: %f dy: %f\n",
537 transformation
.eM11
, transformation
.eM12
,
538 transformation
.eM21
, transformation
.eM22
,
539 transformation
.eDx
, transformation
.eDy
));
541 if (additionalFlags
& 0x08) {
543 EMFP_DEBUG (printf ("EMF+\tuse blend, points: %d\n", (int)blendPoints
));
544 if( blendPoints
<0 || sal_uInt32(blendPoints
)>SAL_MAX_INT32
/(2*sizeof(float)) )
545 blendPoints
= SAL_MAX_INT32
/(2*sizeof(float));
546 blendPositions
= new float [2*blendPoints
];
547 blendFactors
= blendPositions
+ blendPoints
;
548 for (int i
=0; i
< blendPoints
; i
++) {
549 s
>> blendPositions
[i
];
550 EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i
, blendPositions
[i
]));
552 for (int i
=0; i
< blendPoints
; i
++) {
553 s
>> blendFactors
[i
];
554 EMFP_DEBUG (printf ("EMF+\tfactor[%d]: %f\n", i
, blendFactors
[i
]));
558 if (additionalFlags
& 0x04) {
559 s
>> colorblendPoints
;
560 EMFP_DEBUG (printf ("EMF+\tuse color blend, points: %d\n", (int)colorblendPoints
));
561 if( colorblendPoints
<0 || sal_uInt32(colorblendPoints
)>SAL_MAX_INT32
/sizeof(float) )
562 colorblendPoints
= SAL_MAX_INT32
/sizeof(float);
563 if( sal_uInt32(colorblendPoints
)>SAL_MAX_INT32
/sizeof(::Color
) )
564 colorblendPoints
= sal_uInt32(SAL_MAX_INT32
)/sizeof(::Color
);
565 colorblendPositions
= new float [colorblendPoints
];
566 colorblendColors
= new ::Color
[colorblendPoints
];
567 for (int i
=0; i
< colorblendPoints
; i
++) {
568 s
>> colorblendPositions
[i
];
569 EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i
, colorblendPositions
[i
]));
571 for (int i
=0; i
< colorblendPoints
; i
++) {
573 colorblendColors
[i
] = ::Color (0xff - (color
>> 24), (color
>> 16) & 0xff, (color
>> 8) & 0xff, color
& 0xff);
574 EMFP_DEBUG (printf ("EMF+\tcolor[%d]: 0x%08x\n", i
, (unsigned int)color
));
581 EMFP_DEBUG (printf ("EMF+\tunhandled brush type: %08x\n", (unsigned int)type
));
586 struct EMFPPen
: public EMFPBrush
588 XForm transformation
;
597 sal_Int32 dashPatternLen
;
600 sal_Int32 compoundArrayLen
;
601 float *compoundArray
;
602 sal_Int32 customStartCapLen
;
603 sal_uInt8
*customStartCap
;
604 sal_Int32 customEndCapLen
;
605 sal_uInt8
*customEndCap
;
608 EMFPPen () : EMFPBrush ()
612 void SetStrokeAttributes (rendering::StrokeAttributes
& rStrokeAttributes
, ImplRenderer
& rR
, const OutDevState
& rState
)
614 EMFP_DEBUG (if (width
== 0.0) printf ("EMF+\tTODO: pen with zero width - using minimal which might not be correct\n"));
615 rStrokeAttributes
.StrokeWidth
= (rState
.mapModeTransform
* rR
.MapSize (width
== 0.0 ? 0.05 : width
, 0)).getX ();
618 void Read (SvStream
& s
, ImplRenderer
& rR
, sal_Int32
, sal_Int32
)
620 sal_uInt32 header
, unknown
, penFlags
, unknown2
;
623 s
>> header
>> unknown
>> penFlags
>> unknown2
>> width
;
625 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
));
665 if (penFlags
& 256) {
667 if( dashPatternLen
<0 || sal_uInt32(dashPatternLen
)>SAL_MAX_INT32
/sizeof(float) )
668 dashPatternLen
= SAL_MAX_INT32
/sizeof(float);
669 dashPattern
= new float [dashPatternLen
];
670 for (i
= 0; i
< dashPatternLen
; i
++)
671 s
>> dashPattern
[i
];
680 if (penFlags
& 1024) {
681 s
>> compoundArrayLen
;
682 if( compoundArrayLen
<0 || sal_uInt32(compoundArrayLen
)>SAL_MAX_INT32
/sizeof(float) )
683 compoundArrayLen
= SAL_MAX_INT32
/sizeof(float);
684 compoundArray
= new float [compoundArrayLen
];
685 for (i
= 0; i
< compoundArrayLen
; i
++)
686 s
>> compoundArray
[i
];
688 compoundArrayLen
= 0;
690 if (penFlags
& 2048) {
691 s
>> customStartCapLen
;
692 if( customStartCapLen
<0 )
694 customStartCap
= new sal_uInt8
[customStartCapLen
];
695 for (i
= 0; i
< customStartCapLen
; i
++)
696 s
>> customStartCap
[i
];
698 customStartCapLen
= 0;
700 if (penFlags
& 4096) {
701 s
>> customEndCapLen
;
702 if( customEndCapLen
<0 )
704 customEndCap
= new sal_uInt8
[customEndCapLen
];
705 for (i
= 0; i
< customEndCapLen
; i
++)
706 s
>> customEndCap
[i
];
710 EMFPBrush::Read (s
, rR
);
714 struct EMFPImage
: public EMFPObject
720 sal_Int32 pixelFormat
;
724 void Read (SvMemoryStream
&s
, sal_Bool bUseWholeStream
)
726 sal_uInt32 header
, unknown
;
730 EMFP_DEBUG (printf ("EMF+\timage\nEMF+\theader: 0x%08x type: 0x%08x\n", header
, type
));
732 if (type
== 1) { // bitmap
733 s
>> width
>> height
>> stride
>> pixelFormat
>> unknown
;
734 EMFP_DEBUG (printf ("EMF+\tbitmap width: %d height: %d stride: %d pixelFormat: 0x%08x\n", width
, height
, stride
, pixelFormat
));
735 if (width
== 0) { // non native formats
736 GraphicFilter filter
;
738 filter
.ImportGraphic (graphic
, String (), s
);
739 EMFP_DEBUG (printf ("EMF+\tbitmap width: %ld height: %ld\n", graphic
.GetBitmap ().GetSizePixel ().Width (), graphic
.GetBitmap ().GetSizePixel ().Height ()));
742 } else if (type
== 2) {
743 sal_Int32 mfType
, mfSize
;
745 s
>> mfType
>> mfSize
;
746 EMFP_DEBUG (printf ("EMF+\tmetafile type: %d dataSize: %d\n", mfType
, mfSize
));
748 GraphicFilter filter
;
749 // workaround buggy metafiles, which have wrong mfSize set (n#705956 for example)
750 SvMemoryStream
mfStream (((char *)s
.GetData()) + s
.Tell(), bUseWholeStream
? s
.remainingSize() : mfSize
, STREAM_READ
);
752 filter
.ImportGraphic (graphic
, String (), mfStream
);
754 // debug code - write the stream to debug file /tmp/emf-stream.emf
757 static int emfp_debug_stream_numnber
= 0;
758 rtl::OUString
emfp_debug_filename("/tmp/emf-embedded-stream");
759 emfp_debug_filename
+= rtl::OUString::valueOf(emfp_debug_stream_numnber
++);
760 emfp_debug_filename
+= rtl::OUString(".emf");
762 SvFileStream
file( emfp_debug_filename
, STREAM_WRITE
| STREAM_TRUNC
);
772 struct EMFPFont
: public EMFPObject
778 rtl::OUString family
;
780 void Read (SvMemoryStream
&s
)
786 s
>> header
>> emSize
>> sizeUnit
>> fontFlags
>> reserved
>> length
;
788 OSL_ASSERT( ( header
>> 12 ) == 0xdbc01 );
790 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
));
791 EMFP_DEBUG (printf ("EMF+\tflags: 0x%08x reserved: 0x%08x length: 0x%08x\n", (unsigned int)fontFlags
, (unsigned int)reserved
, (unsigned int)length
));
793 if( length
> 0 && length
< 0x4000 ) {
794 sal_Unicode
*chars
= (sal_Unicode
*) alloca( sizeof( sal_Unicode
) * length
);
796 for( sal_uInt32 i
= 0; i
< length
; i
++ )
799 family
= ::rtl::OUString( chars
, length
);
800 EMFP_DEBUG (printf ("EMF+\tfamily: %s\n", rtl::OUStringToOString( family
, RTL_TEXTENCODING_UTF8
).getStr()));
805 void ImplRenderer::ReadRectangle (SvStream
& s
, float& x
, float& y
, float &width
, float& height
, sal_uInt32 flags
)
807 if (flags
& 0x4000) {
808 sal_Int16 ix
, iy
, iw
, ih
;
810 s
>> ix
>> iy
>> iw
>> ih
;
817 s
>> x
>> y
>> width
>> height
;
820 void ImplRenderer::ReadPoint (SvStream
& s
, float& x
, float& y
, sal_uInt32 flags
)
822 if (flags
& 0x4000) {
833 void ImplRenderer::MapToDevice (double& x
, double& y
)
836 x
= 100*nMmX
*x
/nPixX
;
837 y
= 100*nMmY
*y
/nPixY
;
840 ::basegfx::B2DPoint
ImplRenderer::Map (double ix
, double iy
)
844 x
= ix
*aWorldTransform
.eM11
+ iy
*aWorldTransform
.eM21
+ aWorldTransform
.eDx
;
845 y
= ix
*aWorldTransform
.eM12
+ iy
*aWorldTransform
.eM22
+ aWorldTransform
.eDy
;
852 x
*= aBaseTransform
.eM11
;
853 y
*= aBaseTransform
.eM22
;
855 return ::basegfx::B2DPoint (x
, y
);
858 ::basegfx::B2DSize
ImplRenderer::MapSize (double iwidth
, double iheight
)
862 w
= iwidth
*aWorldTransform
.eM11
+ iheight
*aWorldTransform
.eM21
;
863 h
= iwidth
*aWorldTransform
.eM12
+ iheight
*aWorldTransform
.eM22
;
867 w
*= aBaseTransform
.eM11
;
868 h
*= aBaseTransform
.eM22
;
870 return ::basegfx::B2DSize (w
, h
);
874 ::vcl::unotools::colorToDoubleSequence( ::Color (0xff - (x >> 24), \
878 rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace());
879 #define SET_FILL_COLOR(x) \
880 rState.fillColor = COLOR(x);
881 #define SET_LINE_COLOR(x) \
882 rState.lineColor = COLOR(x);
883 #define SET_TEXT_COLOR(x) \
884 rState.textColor = COLOR(x);
886 void ImplRenderer::EMFPPlusFillPolygon (::basegfx::B2DPolyPolygon
& polygon
, const ActionFactoryParameters
& rParms
,
887 OutDevState
& rState
, const CanvasSharedPtr
& rCanvas
, bool isColor
, sal_uInt32 brushIndexOrColor
)
889 ::basegfx::B2DPolyPolygon
localPolygon (polygon
);
891 EMFP_DEBUG (printf ("EMF+\tfill polygon\n"));
893 localPolygon
.transform( rState
.mapModeTransform
);
895 ActionSharedPtr pPolyAction
;
898 EMFP_DEBUG (printf ("EMF+\t\tcolor fill\n"));
900 rState
.isFillColorSet
= true;
901 rState
.isLineColorSet
= false;
902 SET_FILL_COLOR(brushIndexOrColor
);
904 pPolyAction
= ActionSharedPtr ( internal::PolyPolyActionFactory::createPolyPolyAction( localPolygon
, rParms
.mrCanvas
, rState
) );
907 rState
.isFillColorSet
= true;
909 EMFPBrush
* brush
= (EMFPBrush
*) aObjects
[brushIndexOrColor
& 0xff];
910 EMFP_DEBUG (printf ("EMF+\tbrush fill slot: %u (type: %u)\n", (unsigned int)brushIndexOrColor
, (unsigned int)brush
->GetType ()));
912 // give up in case something wrong happened
916 rState
.isFillColorSet
= false;
917 rState
.isLineColorSet
= false;
919 if (brush
->type
== 3 || brush
->type
== 4) {
921 if (brush
->type
== 3 && !(brush
->additionalFlags
& 0x1))
922 return; // we are unable to parse these brushes yet
924 ::basegfx::B2DHomMatrix aTextureTransformation
;
925 ::basegfx::B2DHomMatrix aWorldTransformation
;
926 ::basegfx::B2DHomMatrix aBaseTransformation
;
927 rendering::Texture aTexture
;
929 aWorldTransformation
.set (0, 0, aWorldTransform
.eM11
);
930 aWorldTransformation
.set (0, 1, aWorldTransform
.eM21
);
931 aWorldTransformation
.set (0, 2, aWorldTransform
.eDx
);
932 aWorldTransformation
.set (1, 0, aWorldTransform
.eM12
);
933 aWorldTransformation
.set (1, 1, aWorldTransform
.eM22
);
934 aWorldTransformation
.set (1, 2, aWorldTransform
.eDy
);
936 aBaseTransformation
.set (0, 0, aBaseTransform
.eM11
);
937 aBaseTransformation
.set (0, 1, aBaseTransform
.eM21
);
938 aBaseTransformation
.set (0, 2, aBaseTransform
.eDx
);
939 aBaseTransformation
.set (1, 0, aBaseTransform
.eM12
);
940 aBaseTransformation
.set (1, 1, aBaseTransform
.eM22
);
941 aBaseTransformation
.set (1, 2, aBaseTransform
.eDy
);
943 if (brush
->type
== 4) {
944 aTextureTransformation
.scale (brush
->areaWidth
, brush
->areaHeight
);
945 aTextureTransformation
.translate (brush
->areaX
, brush
->areaY
);
947 aTextureTransformation
.translate (-0.5, -0.5);
948 aTextureTransformation
.scale (brush
->areaWidth
, brush
->areaHeight
);
949 aTextureTransformation
.translate (brush
->areaX
,brush
->areaY
);
952 if (brush
->hasTransformation
) {
953 ::basegfx::B2DHomMatrix aTransformation
;
955 aTransformation
.set (0, 0, brush
->transformation
.eM11
);
956 aTransformation
.set (0, 1, brush
->transformation
.eM21
);
957 aTransformation
.set (0, 2, brush
->transformation
.eDx
);
958 aTransformation
.set (1, 0, brush
->transformation
.eM12
);
959 aTransformation
.set (1, 1, brush
->transformation
.eM22
);
960 aTransformation
.set (1, 2, brush
->transformation
.eDy
);
962 aTextureTransformation
*= aTransformation
;
965 aTextureTransformation
*= aWorldTransformation
;
966 aTextureTransformation
.scale (100.0*nMmX
/nPixX
, 100.0*nMmY
/nPixY
);
967 aTextureTransformation
.translate (-nFrameLeft
, -nFrameTop
);
968 aTextureTransformation
*= rState
.mapModeTransform
;
969 aTextureTransformation
*= aBaseTransformation
;
971 aTexture
.RepeatModeX
= rendering::TexturingMode::CLAMP
;
972 aTexture
.RepeatModeY
= rendering::TexturingMode::CLAMP
;
973 aTexture
.Alpha
= 1.0;
975 basegfx::ODFGradientInfo aGradInfo
;
976 rtl::OUString aGradientService
;
978 const uno::Sequence
< double > aStartColor(
979 ::vcl::unotools::colorToDoubleSequence( brush
->solidColor
,
980 rParms
.mrCanvas
->getUNOCanvas()->getDevice()->getDeviceColorSpace() ) );
981 const uno::Sequence
< double > aEndColor(
982 ::vcl::unotools::colorToDoubleSequence( brush
->secondColor
,
983 rParms
.mrCanvas
->getUNOCanvas()->getDevice()->getDeviceColorSpace() ) );
984 uno::Sequence
< uno::Sequence
< double > > aColors (2);
985 uno::Sequence
< double > aStops (2);
987 if (brush
->blendPositions
) {
988 EMFP_DEBUG (printf ("EMF+\t\tuse blend\n"));
989 aColors
.realloc (brush
->blendPoints
);
990 aStops
.realloc (brush
->blendPoints
);
991 int length
= aStartColor
.getLength ();
992 uno::Sequence
< double > aColor (length
);
994 OSL_ASSERT (length
== aEndColor
.getLength());
996 for (int i
= 0; i
< brush
->blendPoints
; i
++) {
997 aStops
[i
] = brush
->blendPositions
[i
];
999 for (int j
= 0; j
< length
; j
++) {
1000 if (brush
->type
== 4) {
1001 // // gamma correction
1002 // if (brush->additionalFlags & 0x80)
1003 // aColor [j] = pow (aStartColor [j]*(1 - brush->blendFactors[i]) + aEndColor [j]*brush->blendFactors[i], 1/2.2);
1005 aColor
[j
] = aStartColor
[j
]*(1 - brush
->blendFactors
[i
]) + aEndColor
[j
]*brush
->blendFactors
[i
];
1007 aColor
[j
] = aStartColor
[j
]*brush
->blendFactors
[i
] + aEndColor
[j
]*(1 - brush
->blendFactors
[i
]);
1010 aColors
[i
] = aColor
;
1012 } else if (brush
->colorblendPositions
) {
1013 EMFP_DEBUG (printf ("EMF+\t\tuse color blend\n"));
1014 aColors
.realloc (brush
->colorblendPoints
);
1015 aStops
.realloc (brush
->colorblendPoints
);
1017 for (int i
= 0; i
< brush
->colorblendPoints
; i
++) {
1018 aStops
[i
] = brush
->colorblendPositions
[i
];
1019 aColors
[(brush
->type
== 4) ? i
: brush
->colorblendPoints
- 1 - i
] = ::vcl::unotools::colorToDoubleSequence( brush
->colorblendColors
[i
],
1020 rParms
.mrCanvas
->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
1026 if (brush
->type
== 4) {
1027 aColors
[0] = aStartColor
;
1028 aColors
[1] = aEndColor
;
1030 aColors
[1] = aStartColor
;
1031 aColors
[0] = aEndColor
;
1035 EMFP_DEBUG (printf ("EMF+\t\tset gradient\n"));
1036 basegfx::B2DRange
aBoundsRectangle (0, 0, 1, 1);
1037 if (brush
->type
== 4) {
1038 aGradientService
= "LinearGradient";
1039 basegfx::tools::createLinearODFGradientInfo( aGradInfo
,
1046 aGradientService
= "EllipticalGradient";
1047 basegfx::tools::createEllipticalODFGradientInfo( aGradInfo
,
1049 ::basegfx::B2DVector( 0, 0 ),
1055 uno::Reference
< lang::XMultiServiceFactory
> xFactory(
1056 rParms
.mrCanvas
->getUNOCanvas()->getDevice()->getParametricPolyPolygonFactory() );
1058 if( xFactory
.is() ) {
1059 uno::Sequence
<uno::Any
> args( 3 );
1060 beans::PropertyValue aProp
;
1061 aProp
.Name
= "Colors";
1062 aProp
.Value
<<= aColors
;
1064 aProp
.Name
= "Stops";
1065 aProp
.Value
<<= aStops
;
1067 aProp
.Name
= "AspectRatio";
1068 aProp
.Value
<<= static_cast<sal_Int32
>(1);
1071 aTexture
.Gradient
.set(
1072 xFactory
->createInstanceWithArguments( aGradientService
,
1077 ::basegfx::unotools::affineMatrixFromHomMatrix( aTexture
.AffineTransform
,
1078 aTextureTransformation
);
1080 if( aTexture
.Gradient
.is() )
1082 ActionSharedPtr ( internal::PolyPolyActionFactory::createPolyPolyAction( localPolygon
,
1091 EMFP_DEBUG (printf ("EMF+\t\tadd poly action\n"));
1093 maActions
.push_back(
1096 rParms
.mrCurrActionIndex
) );
1098 rParms
.mrCurrActionIndex
+= pPolyAction
->getActionCount()-1;
1102 void ImplRenderer::processObjectRecord(SvMemoryStream
& rObjectStream
, sal_uInt16 flags
, sal_Bool bUseWholeStream
)
1106 EMFP_DEBUG (printf ("EMF+ Object slot: %hd flags: %hx\n", flags
& 0xff, flags
& 0xff00));
1108 index
= flags
& 0xff;
1109 if (aObjects
[index
] != NULL
) {
1110 delete aObjects
[index
];
1111 aObjects
[index
] = NULL
;
1114 switch (flags
& 0x7f00) {
1115 case EmfPlusObjectTypeBrush
:
1118 aObjects
[index
] = brush
= new EMFPBrush ();
1119 brush
->Read (rObjectStream
, *this);
1123 case EmfPlusObjectTypePen
:
1126 aObjects
[index
] = pen
= new EMFPPen ();
1127 pen
->Read (rObjectStream
, *this, nHDPI
, nVDPI
);
1131 case EmfPlusObjectTypePath
:
1132 sal_uInt32 header
, pathFlags
;
1135 rObjectStream
>> header
>> points
>> pathFlags
;
1137 EMFP_DEBUG (printf ("EMF+\tpath\n"));
1138 EMFP_DEBUG (printf ("EMF+\theader: 0x%08x points: %d additional flags: 0x%08x\n", (unsigned int)header
, (int)points
, (unsigned int)pathFlags
));
1141 aObjects
[index
] = path
= new EMFPPath (points
);
1142 path
->Read (rObjectStream
, pathFlags
, *this);
1145 case EmfPlusObjectTypeRegion
: {
1148 aObjects
[index
] = region
= new EMFPRegion ();
1149 region
->Read (rObjectStream
);
1153 case EmfPlusObjectTypeImage
:
1156 aObjects
[index
] = image
= new EMFPImage ();
1157 image
->Read (rObjectStream
, bUseWholeStream
);
1161 case EmfPlusObjectTypeFont
:
1164 aObjects
[index
] = font
= new EMFPFont ();
1165 font
->Read (rObjectStream
);
1170 EMFP_DEBUG (printf ("EMF+\tObject unhandled flags: 0x%04x\n", flags
& 0xff00));
1175 static XubString
readString (SvMemoryStream
& rMF
, sal_uInt32 stringLength
)
1177 sal_uInt16
*chars
= new sal_uInt16
[stringLength
];
1179 for( sal_uInt32 i
=0; i
<stringLength
; i
++) {
1181 EMFP_DEBUG (printf ("EMF+\tglyph[%u]: 0x%04x\n",
1182 (unsigned int)i
, chars
[i
]));
1185 // create and add the text action
1186 XubString
text( chars
, stringLength
);
1193 double ImplRenderer::setFont (sal_uInt8 objectId
, const ActionFactoryParameters
& rParms
, OutDevState
& rState
)
1195 EMFPFont
*font
= (EMFPFont
*) aObjects
[ objectId
];
1197 rendering::FontRequest aFontRequest
;
1198 aFontRequest
.FontDescription
.FamilyName
= font
->family
;
1199 double cellSize
= font
->emSize
;
1200 aFontRequest
.CellSize
= (rState
.mapModeTransform
*MapSize( cellSize
, 0 )).getX();
1201 rState
.xFont
= rParms
.mrCanvas
->getUNOCanvas()->createFont( aFontRequest
,
1202 uno::Sequence
< beans::PropertyValue
>(),
1203 geometry::Matrix2D() );
1208 void ImplRenderer::processEMFPlus( MetaCommentAction
* pAct
, const ActionFactoryParameters
& rFactoryParms
,
1209 OutDevState
& rState
, const CanvasSharedPtr
& rCanvas
)
1211 sal_uInt32 length
= pAct
->GetDataSize ();
1212 SvMemoryStream
rMF ((void*) pAct
->GetData (), length
, STREAM_READ
);
1216 while (length
> 0) {
1217 sal_uInt16 type
, flags
;
1218 sal_uInt32 size
, dataSize
;
1221 rMF
>> type
>> flags
>> size
>> dataSize
;
1223 next
= rMF
.Tell() + ( size
- 12 );
1225 EMFP_DEBUG (printf ("EMF+ record size: %u type: %04hx flags: %04hx data size: %u\n", (unsigned int)size
, type
, flags
, (unsigned int)dataSize
));
1227 if (type
== EmfPlusRecordTypeObject
&& ((mbMultipart
&& (flags
& 0x7fff) == (mMFlags
& 0x7fff)) || (flags
& 0x8000))) {
1234 // 1st 4 bytes are unknown
1235 mMStream
.Write (((const char *)rMF
.GetData()) + rMF
.Tell() + 4, dataSize
- 4);
1236 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
));
1239 EMFP_DEBUG (printf ("EMF+ multipart record flags: %04hx\n", mMFlags
));
1241 processObjectRecord (mMStream
, mMFlags
, sal_True
);
1243 mbMultipart
= false;
1246 if (type
!= EmfPlusRecordTypeObject
|| !(flags
& 0x8000))
1248 case EmfPlusRecordTypeHeader
:
1249 sal_uInt32 header
, version
;
1251 rMF
>> header
>> version
>> nHDPI
>> nVDPI
;
1253 EMFP_DEBUG (printf ("EMF+ Header\n"));
1254 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)));
1257 case EmfPlusRecordTypeEndOfFile
:
1258 EMFP_DEBUG (printf ("EMF+ EndOfFile\n"));
1260 case EmfPlusRecordTypeGetDC
:
1261 EMFP_DEBUG (printf ("EMF+ GetDC\n"));
1262 EMFP_DEBUG (printf ("EMF+\talready used in svtools wmf/emf filter parser\n"));
1264 case EmfPlusRecordTypeObject
:
1265 processObjectRecord (rMF
, flags
);
1267 case EmfPlusRecordTypeFillPie
:
1269 sal_uInt32 brushIndexOrColor
;
1270 float startAngle
, sweepAngle
;
1272 rMF
>> brushIndexOrColor
>> startAngle
>> sweepAngle
;
1274 EMFP_DEBUG (printf ("EMF+ FillPie colorOrIndex: %x startAngle: %f sweepAngle: %f\n", (unsigned int)brushIndexOrColor
, startAngle
, sweepAngle
));
1276 float dx
, dy
, dw
, dh
;
1278 ReadRectangle (rMF
, dx
, dy
, dw
, dh
, flags
& 0x4000);
1280 EMFP_DEBUG (printf ("EMF+ RectData: %f,%f %fx%f\n", dx
, dy
, dw
, dh
));
1282 startAngle
= 2*M_PI
*startAngle
/360;
1283 sweepAngle
= 2*M_PI
*sweepAngle
/360;
1285 B2DPoint
mappedCenter (Map (dx
+ dw
/2, dy
+ dh
/2));
1286 B2DSize
mappedSize( MapSize (dw
/2, dh
/2));
1288 double endAngle
= startAngle
+ sweepAngle
;
1291 endAngle
= fmod (endAngle
, M_PI
*2);
1293 if (sweepAngle
< 0) {
1294 double tmp
= startAngle
;
1295 startAngle
= endAngle
;
1299 EMFP_DEBUG (printf ("EMF+ angles: %f,%f ---> %f,%f\n", startAngle
, sweepAngle
, startAngle
, endAngle
));
1301 B2DPolygon polygon
= tools::createPolygonFromEllipseSegment (mappedCenter
, mappedSize
.getX (), mappedSize
.getY (), startAngle
, endAngle
);
1302 polygon
.append (mappedCenter
);
1303 polygon
.setClosed (true);
1305 B2DPolyPolygon
polyPolygon (polygon
);
1306 EMFPPlusFillPolygon (polyPolygon
, rFactoryParms
, rState
, rCanvas
, flags
& 0x8000, brushIndexOrColor
);
1309 case EmfPlusRecordTypeFillPath
:
1311 sal_uInt32 index
= flags
& 0xff;
1312 sal_uInt32 brushIndexOrColor
;
1314 rMF
>> brushIndexOrColor
;
1316 EMFP_DEBUG (printf ("EMF+ FillPath slot: %u\n", (unsigned int)index
));
1318 EMFPPlusFillPolygon (((EMFPPath
*) aObjects
[index
])->GetPolygon (*this), rFactoryParms
, rState
, rCanvas
, flags
& 0x8000, brushIndexOrColor
);
1321 case EmfPlusRecordTypeFillRects
:
1323 EMFP_DEBUG (printf ("EMF+ FillRects\n"));
1325 sal_uInt32 brushIndexOrColor
;
1326 sal_Int32 rectangles
;
1327 ::basegfx::B2DPolygon polygon
;
1329 rMF
>> brushIndexOrColor
>> rectangles
;
1331 EMFP_DEBUG (printf ("EMF+\t%s: 0x%08x\n", (flags
& 0x8000) ? "color" : "brush index", (unsigned int)brushIndexOrColor
));
1333 for (int i
=0; i
< rectangles
; i
++) {
1334 if (flags
& 0x4000) {
1335 /* 16bit integers */
1336 sal_Int16 x
, y
, width
, height
;
1338 rMF
>> x
>> y
>> width
>> height
;
1340 polygon
.append (Map (x
, y
));
1341 polygon
.append (Map (x
+ width
, y
));
1342 polygon
.append (Map (x
+ width
, y
+ height
));
1343 polygon
.append (Map (x
, y
+ height
));
1345 EMFP_DEBUG (printf ("EMF+\trectangle: %d,%d %dx%d\n", x
, y
, width
, height
));
1348 float x
, y
, width
, height
;
1350 rMF
>> x
>> y
>> width
>> height
;
1352 polygon
.append (Map (x
, y
));
1353 polygon
.append (Map (x
+ width
, y
));
1354 polygon
.append (Map (x
+ width
, y
+ height
));
1355 polygon
.append (Map (x
, y
+ height
));
1357 EMFP_DEBUG (printf ("EMF+\trectangle: %f,%f %fx%f\n", x
, y
, width
, height
));
1360 ::basegfx::B2DPolyPolygon
polyPolygon (polygon
);
1362 EMFPPlusFillPolygon (polyPolygon
, rFactoryParms
, rState
, rCanvas
, flags
& 0x8000, brushIndexOrColor
);
1366 case EmfPlusRecordTypeFillPolygon
:
1368 EMFP_DEBUG (sal_uInt8 index
= flags
& 0xff);
1369 sal_uInt32 brushIndexOrColor
;
1372 rMF
>> brushIndexOrColor
;
1375 EMFP_DEBUG (printf ("EMF+ FillPolygon in slot: %d points: %d\n", index
, points
));
1376 EMFP_DEBUG (printf ("EMF+\t%s: 0x%08x\n", (flags
& 0x8000) ? "color" : "brush index", brushIndexOrColor
));
1378 EMFPPath
path (points
, true);
1379 path
.Read (rMF
, flags
, *this);
1382 EMFPPlusFillPolygon (path
.GetPolygon (*this), rFactoryParms
, rState
, rCanvas
, flags
& 0x8000, brushIndexOrColor
);
1386 case EmfPlusRecordTypeDrawLines
:
1388 sal_uInt32 index
= flags
& 0xff;
1393 EMFP_DEBUG (printf ("EMF+ DrawLines in slot: %u points: %u\n", (unsigned int)index
, (unsigned int)points
));
1395 EMFPPath
path (points
, true);
1396 path
.Read (rMF
, flags
, *this);
1398 EMFPPen
* pen
= (EMFPPen
*) aObjects
[index
];
1400 rState
.isFillColorSet
= false;
1401 rState
.isLineColorSet
= true;
1402 rState
.lineColor
= ::vcl::unotools::colorToDoubleSequence (pen
->GetColor (),
1403 rCanvas
->getUNOCanvas ()->getDevice()->getDeviceColorSpace() );
1404 ::basegfx::B2DPolyPolygon
& polygon (path
.GetPolygon (*this));
1406 polygon
.transform( rState
.mapModeTransform
);
1408 rendering::StrokeAttributes aStrokeAttributes
;
1410 pen
->SetStrokeAttributes (aStrokeAttributes
, *this, rState
);
1412 ActionSharedPtr
pPolyAction(
1413 internal::PolyPolyActionFactory::createPolyPolyAction(
1414 polygon
, rFactoryParms
.mrCanvas
, rState
, aStrokeAttributes
) );
1418 maActions
.push_back(
1421 rFactoryParms
.mrCurrActionIndex
) );
1423 rFactoryParms
.mrCurrActionIndex
+= pPolyAction
->getActionCount()-1;
1428 case EmfPlusRecordTypeDrawPath
:
1430 sal_uInt32 penIndex
;
1434 EMFP_DEBUG (printf ("EMF+ DrawPath\n"));
1435 EMFP_DEBUG (printf ("EMF+\tpen: %u\n", (unsigned int)penIndex
));
1437 EMFPPath
* path
= (EMFPPath
*) aObjects
[flags
& 0xff];
1438 EMFPPen
* pen
= (EMFPPen
*) aObjects
[penIndex
& 0xff];
1440 SAL_WARN_IF( !pen
, "cppcanvas", "EmfPlusRecordTypeDrawPath missing pen" );
1441 SAL_WARN_IF( !path
, "cppcanvas", "EmfPlusRecordTypeDrawPath missing path" );
1445 rState
.isFillColorSet
= false;
1446 rState
.isLineColorSet
= true;
1447 rState
.lineColor
= ::vcl::unotools::colorToDoubleSequence (pen
->GetColor (),
1448 rCanvas
->getUNOCanvas ()->getDevice()->getDeviceColorSpace());
1449 ::basegfx::B2DPolyPolygon
& polygon (path
->GetPolygon (*this));
1451 polygon
.transform( rState
.mapModeTransform
);
1452 rendering::StrokeAttributes aStrokeAttributes
;
1454 pen
->SetStrokeAttributes (aStrokeAttributes
, *this, rState
);
1456 ActionSharedPtr
pPolyAction(
1457 internal::PolyPolyActionFactory::createPolyPolyAction(
1458 polygon
, rFactoryParms
.mrCanvas
, rState
, aStrokeAttributes
) );
1462 maActions
.push_back(
1465 rFactoryParms
.mrCurrActionIndex
) );
1467 rFactoryParms
.mrCurrActionIndex
+= pPolyAction
->getActionCount()-1;
1472 case EmfPlusRecordTypeDrawImagePoints
:
1474 sal_uInt32 attrIndex
;
1475 sal_Int32 sourceUnit
;
1477 rMF
>> attrIndex
>> sourceUnit
;
1479 EMFP_DEBUG (printf ("EMF+ DrawImagePoints attributes index: %d source unit: %d\n", (int)attrIndex
, (int)sourceUnit
));
1480 EMFP_DEBUG (printf ("EMF+\tTODO: use image attributes\n"));
1482 if (sourceUnit
== 2 && aObjects
[flags
& 0xff]) { // we handle only GraphicsUnit.Pixel now
1483 EMFPImage
& image
= *(EMFPImage
*) aObjects
[flags
& 0xff];
1484 float sx
, sy
, sw
, sh
;
1487 ReadRectangle (rMF
, sx
, sy
, sw
, sh
);
1491 EMFP_DEBUG (printf ("EMF+ DrawImagePoints source rectangle: %f,%f %fx%f unknown: 0x%08x\n", sx
, sy
, sw
, sh
, (unsigned int)unknown
));
1493 if (unknown
== 3) { // it probably means number of points defining destination rectangle
1494 float x1
, y1
, x2
, y2
, x3
, y3
;
1496 ReadPoint (rMF
, x1
, y1
, flags
);
1497 ReadPoint (rMF
, x2
, y2
, flags
);
1498 ReadPoint (rMF
, x3
, y3
, flags
);
1500 BitmapEx
aBmp( image
.graphic
.GetBitmapEx () );
1501 const Rectangle
aCropRect (::vcl::unotools::pointFromB2DPoint (basegfx::B2DPoint (sx
, sy
)),
1502 ::vcl::unotools::sizeFromB2DSize (basegfx::B2DSize(sw
, sh
)));
1503 aBmp
.Crop( aCropRect
);
1506 Size
aSize( aBmp
.GetSizePixel() );
1507 if( aSize
.Width() > 0 && aSize
.Height() > 0 ) {
1508 ActionSharedPtr
pBmpAction (
1509 internal::BitmapActionFactory::createBitmapAction (
1511 rState
.mapModeTransform
* Map (x1
, y1
),
1512 rState
.mapModeTransform
* MapSize(x2
- x1
, y3
- y1
),
1517 maActions
.push_back( MtfAction( pBmpAction
,
1518 rFactoryParms
.mrCurrActionIndex
) );
1520 rFactoryParms
.mrCurrActionIndex
+= pBmpAction
->getActionCount()-1;
1523 EMFP_DEBUG (printf ("EMF+ warning: empty bitmap\n"));
1526 EMFP_DEBUG (printf ("EMF+ DrawImagePoints TODO (fixme)\n"));
1529 EMFP_DEBUG (printf ("EMF+ DrawImagePoints TODO (fixme) - possibly unsupported source units for crop rectangle\n"));
1533 case EmfPlusRecordTypeDrawString
:
1535 EMFP_DEBUG (printf ("EMF+ DrawString\n"));
1538 sal_uInt32 formatId
;
1539 sal_uInt32 stringLength
;
1541 rMF
>> brushId
>> formatId
>> stringLength
;
1542 EMFP_DEBUG (printf ("EMF+ DrawString brushId: %x formatId: %x length: %x\n", brushId
, formatId
, stringLength
));
1544 if (flags
& 0x8000) {
1545 float lx
, ly
, lw
, lh
;
1547 rMF
>> lx
>> ly
>> lw
>> lh
;
1549 EMFP_DEBUG (printf ("EMF+ DrawString layoutRect: %f,%f - %fx%f\n", lx
, ly
, lw
, lh
));
1551 XubString text
= readString ( rMF
, stringLength
);
1553 double cellSize
= setFont (flags
& 0xff, rFactoryParms
, rState
);
1554 SET_TEXT_COLOR( brushId
);
1556 ActionSharedPtr
pTextAction(
1557 TextActionFactory::createTextAction(
1558 // position is just rough guess for now
1559 // we should calculate it exactly from layoutRect or font
1560 ::vcl::unotools::pointFromB2DPoint ( Map( lx
+ 0.15*cellSize
, ly
+ cellSize
) ),
1569 rFactoryParms
.mrVDev
,
1570 rFactoryParms
.mrCanvas
,
1572 rFactoryParms
.mrParms
,
1576 EMFP_DEBUG (printf ("EMF+\t\tadd text action\n"));
1578 maActions
.push_back(
1581 rFactoryParms
.mrCurrActionIndex
) );
1583 rFactoryParms
.mrCurrActionIndex
+= pTextAction
->getActionCount()-1;
1586 EMFP_DEBUG (printf ("EMF+ DrawString TODO - drawing with brush not yet supported\n"));
1590 case EmfPlusRecordTypeSetPageTransform
:
1593 EMFP_DEBUG (printf ("EMF+ SetPageTransform\n"));
1594 EMFP_DEBUG (printf ("EMF+\tscale: %f unit: %d\n", fPageScale
, flags
));
1595 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1597 case EmfPlusRecordTypeSetRenderingOrigin
:
1598 rMF
>> nOriginX
>> nOriginY
;
1599 EMFP_DEBUG (printf ("EMF+ SetRenderingOrigin\n"));
1600 EMFP_DEBUG (printf ("EMF+\torigin [x,y]: %d,%d\n", (int)nOriginX
, (int)nOriginY
));
1602 case EmfPlusRecordTypeSetTextRenderingHint
:
1603 EMFP_DEBUG (printf ("EMF+ SetTextRenderingHint\n"));
1604 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1606 case EmfPlusRecordTypeSetAntiAliasMode
:
1607 EMFP_DEBUG (printf ("EMF+ SetAntiAliasMode\n"));
1608 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1610 case EmfPlusRecordTypeSetInterpolationMode
:
1611 EMFP_DEBUG (printf ("EMF+ InterpolationMode\n"));
1612 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1614 case EmfPlusRecordTypeSetPixelOffsetMode
:
1615 EMFP_DEBUG (printf ("EMF+ SetPixelOffsetMode\n"));
1616 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1618 case EmfPlusRecordTypeSetCompositingQuality
:
1619 EMFP_DEBUG (printf ("EMF+ SetCompositingQuality\n"));
1620 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1622 case EmfPlusRecordTypeSave
:
1623 EMFP_DEBUG (printf ("EMF+ Save\n"));
1624 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1626 case EmfPlusRecordTypeSetWorldTransform
: {
1627 EMFP_DEBUG (printf ("EMF+ SetWorldTransform\n"));
1630 aWorldTransform
.Set (transform
);
1631 EMFP_DEBUG (printf ("EMF+\tm11: %f m12: %f\nEMF+\tm21: %f m22: %f\nEMF+\tdx: %f dy: %f\n",
1632 aWorldTransform
.eM11
, aWorldTransform
.eM12
,
1633 aWorldTransform
.eM21
, aWorldTransform
.eM22
,
1634 aWorldTransform
.eDx
, aWorldTransform
.eDy
));
1637 case EmfPlusRecordTypeResetWorldTransform
:
1638 EMFP_DEBUG (printf ("EMF+ ResetWorldTransform\n"));
1639 aWorldTransform
.SetIdentity ();
1641 case EmfPlusRecordTypeMultiplyWorldTransform
: {
1642 EMFP_DEBUG (printf ("EMF+ MultiplyWorldTransform\n"));
1646 EMFP_DEBUG (printf ("EMF+\tmatrix m11: %f m12: %f\nEMF+\tm21: %f m22: %f\nEMF+\tdx: %f dy: %f\n",
1647 transform
.eM11
, transform
.eM12
,
1648 transform
.eM21
, transform
.eM22
,
1649 transform
.eDx
, transform
.eDy
));
1651 if (flags
& 0x2000) // post multiply
1652 aWorldTransform
.Multiply (transform
);
1653 else { // pre multiply
1654 transform
.Multiply (aWorldTransform
);
1655 aWorldTransform
.Set (transform
);
1657 EMFP_DEBUG (printf ("EMF+\tresult world matrix m11: %f m12: %f\nEMF+\tm21: %f m22: %f\nEMF+\tdx: %f dy: %f\n",
1658 aWorldTransform
.eM11
, aWorldTransform
.eM12
,
1659 aWorldTransform
.eM21
, aWorldTransform
.eM22
,
1660 aWorldTransform
.eDx
, aWorldTransform
.eDy
));
1663 case EmfPlusRecordTypeSetClipPath
:
1665 EMFP_DEBUG (printf ("EMF+ SetClipPath\n"));
1666 EMFP_DEBUG (printf ("EMF+\tpath in slot: %d\n", flags
& 0xff));
1668 EMFPPath
& path
= *(EMFPPath
*) aObjects
[flags
& 0xff];
1669 ::basegfx::B2DPolyPolygon
& clipPoly (path
.GetPolygon (*this));
1671 clipPoly
.transform (rState
.mapModeTransform
);
1672 updateClipping (clipPoly
, rFactoryParms
, false);
1676 case EmfPlusRecordTypeSetClipRegion
: {
1677 EMFP_DEBUG (printf ("EMF+ SetClipRegion\n"));
1678 EMFP_DEBUG (printf ("EMF+\tregion in slot: %d combine mode: %d\n", flags
& 0xff, (flags
& 0xff00) >> 8));
1679 EMFPRegion
*region
= (EMFPRegion
*)aObjects
[flags
& 0xff];
1682 if (region
&& region
->parts
== 0 && region
->initialState
== EmfPlusRegionInitialStateInfinite
) {
1683 updateClipping (::basegfx::B2DPolyPolygon (), rFactoryParms
, false);
1685 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1689 case EmfPlusRecordTypeDrawDriverString
: {
1690 EMFP_DEBUG (printf ("EMF+ DrawDriverString, flags: 0x%04x\n", flags
));
1691 sal_uInt32 brushIndexOrColor
;
1692 sal_uInt32 optionFlags
;
1693 sal_uInt32 hasMatrix
;
1694 sal_uInt32 glyphsCount
;
1696 rMF
>> brushIndexOrColor
>> optionFlags
>> hasMatrix
>> glyphsCount
;
1698 EMFP_DEBUG (printf ("EMF+\t%s: 0x%08x\n", (flags
& 0x8000) ? "color" : "brush index", (unsigned int)brushIndexOrColor
));
1699 EMFP_DEBUG (printf ("EMF+\toption flags: 0x%08x\n", (unsigned int)optionFlags
));
1700 EMFP_DEBUG (printf ("EMF+\thas matrix: %u\n", (unsigned int)hasMatrix
));
1701 EMFP_DEBUG (printf ("EMF+\tglyphs: %u\n", (unsigned int)glyphsCount
));
1703 if( ( optionFlags
& 1 ) && glyphsCount
> 0 ) {
1704 float *charsPosX
= new float[glyphsCount
];
1705 float *charsPosY
= new float[glyphsCount
];
1707 XubString text
= readString (rMF
, glyphsCount
);
1709 for( sal_uInt32 i
=0; i
<glyphsCount
; i
++) {
1710 rMF
>> charsPosX
[i
] >> charsPosY
[i
];
1711 EMFP_DEBUG (printf ("EMF+\tglyphPosition[%u]: %f, %f\n", (unsigned int)i
, charsPosX
[i
], charsPosY
[i
]));
1717 EMFP_DEBUG (printf ("EMF+\tmatrix:: %f, %f, %f, %f, %f, %f\n", transform
.eM11
, transform
.eM12
, transform
.eM21
, transform
.eM22
, transform
.eDx
, transform
.eDy
));
1720 // add the text action
1721 setFont (flags
& 0xff, rFactoryParms
, rState
);
1723 if( flags
& 0x8000 )
1724 SET_TEXT_COLOR(brushIndexOrColor
);
1726 ActionSharedPtr
pTextAction(
1727 TextActionFactory::createTextAction(
1728 ::vcl::unotools::pointFromB2DPoint ( Map( charsPosX
[0], charsPosY
[0] ) ),
1737 rFactoryParms
.mrVDev
,
1738 rFactoryParms
.mrCanvas
,
1740 rFactoryParms
.mrParms
,
1745 EMFP_DEBUG (printf ("EMF+\t\tadd text action\n"));
1747 maActions
.push_back(
1750 rFactoryParms
.mrCurrActionIndex
) );
1752 rFactoryParms
.mrCurrActionIndex
+= pTextAction
->getActionCount()-1;
1758 EMFP_DEBUG (printf ("EMF+\tTODO: fonts (non-unicode glyphs chars)\n"));
1764 EMFP_DEBUG (printf ("EMF+ unhandled record type: %d\n", type
));
1765 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1776 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */