merge the formfield patch from ooo-build
[ooovba.git] / cppcanvas / source / mtfrenderer / emfplus.cxx
blob3194009fc2bedb2bc74d4bdb5689b5aa1236e08b
1 #include <tools/stream.hxx>
2 #include <vcl/metaact.hxx>
3 #include <svtools/filter.hxx>
4 #include <basegfx/tools/canvastools.hxx>
5 #include <basegfx/tools/tools.hxx>
6 #include <basegfx/numeric/ftools.hxx>
7 #include <basegfx/point/b2dpoint.hxx>
8 #include <basegfx/vector/b2dsize.hxx>
9 #include <basegfx/range/b2drange.hxx>
10 #include <basegfx/range/b2drectangle.hxx>
11 #include <basegfx/polygon/b2dpolygon.hxx>
12 #include <basegfx/polygon/b2dpolypolygon.hxx>
13 #include <basegfx/polygon/b2dpolypolygontools.hxx>
14 #include <vcl/canvastools.hxx>
15 #include <rtl/ustring.hxx>
17 #include <com/sun/star/rendering/XCanvas.hpp>
18 #include <com/sun/star/rendering/TexturingMode.hpp>
19 #include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
21 #include <bitmapaction.hxx>
22 #include <implrenderer.hxx>
23 #include <outdevstate.hxx>
24 #include <polypolyaction.hxx>
25 #include <textaction.hxx>
27 #define EmfPlusRecordTypeHeader 16385
28 #define EmfPlusRecordTypeEndOfFile 16386
29 #define EmfPlusRecordTypeGetDC 16388
30 #define EmfPlusRecordTypeObject 16392
31 #define EmfPlusRecordTypeFillRects 16394
32 #define EmfPlusRecordTypeFillPolygon 16396
33 #define EmfPlusRecordTypeDrawLines 16397
34 #define EmfPlusRecordTypeFillPath 16404
35 #define EmfPlusRecordTypeDrawPath 16405
36 #define EmfPlusRecordTypeDrawImagePoints 16411
37 #define EmfPlusRecordTypeDrawString 16412
38 #define EmfPlusRecordTypeSetRenderingOrigin 16413
39 #define EmfPlusRecordTypeSetAntiAliasMode 16414
40 #define EmfPlusRecordTypeSetTextRenderingHint 16415
41 #define EmfPlusRecordTypeSetInterpolationMode 16417
42 #define EmfPlusRecordTypeSetPixelOffsetMode 16418
43 #define EmfPlusRecordTypeSetCompositingQuality 16420
44 #define EmfPlusRecordTypeSave 16421
45 #define EmfPlusRecordTypeSetWorldTransform 16426
46 #define EmfPlusRecordTypeResetWorldTransform 16427
47 #define EmfPlusRecordTypeSetPageTransform 16432
48 #define EmfPlusRecordTypeSetClipPath 16435
49 #define EmfPlusRecordTypeSetClipRegion 16436
50 #define EmfPlusRecordTypeDrawDriverString 16438
52 #define EmfPlusObjectTypeBrush 0x100
53 #define EmfPlusObjectTypePen 0x200
54 #define EmfPlusObjectTypePath 0x300
55 #define EmfPlusObjectTypeRegion 0x400
56 #define EmfPlusObjectTypeImage 0x500
57 #define EmfPlusObjectTypeFont 0x600
58 #define EmfPlusObjectTypeStringFormat 0x700
59 #define EmfPlusObjectTypeImageAttributes 0x800
61 #define EmfPlusRegionInitialStateRectangle 0x10000000
62 #define EmfPlusRegionInitialStatePath 0x10000001
63 #define EmfPlusRegionInitialStateEmpty 0x10000002
64 #define EmfPlusRegionInitialStateInfinite 0x10000003
66 #define EMFP_DEBUG(x)
67 //#define EMFP_DEBUG(x) x
69 using namespace ::com::sun::star;
71 namespace cppcanvas
73 namespace internal
76 EMFP_DEBUG (void dumpWords (SvStream& s, int i)
78 sal_uInt32 pos = s.Tell ();
79 INT16 data;
80 for (; i > 0; i --) {
81 s >> data;
82 printf ("EMF+\tdata: %04hX\n", data);
84 s.Seek (pos);
85 });
87 struct EMFPObject
91 struct EMFPPath : public EMFPObject
93 ::basegfx::B2DPolyPolygon aPolygon;
94 sal_Int32 nPoints;
95 float* pPoints;
96 sal_uInt8* pPointTypes;
98 public:
99 EMFPPath (sal_Int32 _nPoints, bool bLines = false)
101 if( _nPoints<0 || _nPoints>SAL_MAX_INT32/(2*sizeof(float)) )
102 _nPoints = SAL_MAX_INT32/(2*sizeof(float));
103 nPoints = _nPoints;
104 pPoints = new float [nPoints*2];
105 if (!bLines)
106 pPointTypes = new sal_uInt8 [_nPoints];
107 else
108 pPointTypes = NULL;
111 ~EMFPPath ()
113 delete [] pPoints;
114 delete [] pPointTypes;
117 // TODO: remove rR argument when debug code is not longer needed
118 void Read (SvStream& s, UINT32 pathFlags, ImplRenderer& rR)
120 for (int i = 0; i < nPoints; i ++) {
121 if (pathFlags & 0x4000) {
122 // points are stored in short 16bit integer format
123 UINT16 x, y;
125 s >> x >> y;
126 EMFP_DEBUG (printf ("EMF+\tpoint [x,y]: %hd,%hd\n", x, y));
127 pPoints [i*2] = x;
128 pPoints [i*2 + 1] = y;
129 } else {
130 // points are stored in Single (float) format
131 s >> pPoints [i*2] >> pPoints [i*2 + 1];
132 EMFP_DEBUG (printf ("EMF+\tpoint [x,y]: %f,%f\n", pPoints [i*2], pPoints [i*2 + 1]));
136 if (pPointTypes)
137 for (int i = 0; i < nPoints; i ++) {
138 UINT8 pathType;
140 s >> pPointTypes [i];
141 EMFP_DEBUG (printf ("EMF+\tpoint type: %x\n", pPointTypes [i]));
144 aPolygon.clear ();
146 // debug code
147 const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (GetPolygon (rR)));
148 EMFP_DEBUG (printf ("EMF+\tpolygon bounding box: %f,%f %fx%f (mapped)\n", aBounds.getMinX (), aBounds.getMinY (), aBounds.getWidth (), aBounds.getHeight ()));
151 ::basegfx::B2DPolyPolygon& GetPolygon (ImplRenderer& rR, bool bMapIt = true)
153 ::basegfx::B2DPolygon polygon;
154 sal_Int32 points = nPoints;
156 aPolygon.clear ();
158 int last_normal = 0, p = 0;
159 ::basegfx::B2DPoint prev, mapped;
160 bool hasPrev = false;
161 for (int i = 0; i < nPoints; i ++) {
162 if (p && pPointTypes && (pPointTypes [i] == 0)) {
163 aPolygon.append (polygon);
164 last_normal = i;
165 p = 0;
166 polygon.clear ();
169 if (bMapIt)
170 mapped = rR.Map (pPoints [i*2], pPoints [i*2 + 1]);
171 else
172 mapped = ::basegfx::B2DPoint (pPoints [i*2], pPoints [i*2 + 1]);
173 //EMFP_DEBUG (printf ("polygon point: %f,%f mapped: %f,%f\n", pPoints [i*2], pPoints [i*2 + 1], mapped.getX (), mapped.getY ()));
174 if (pPointTypes) {
175 if ((pPointTypes [i] & 0x07) == 3) {
176 if (((i - last_normal )% 3) == 1) {
177 polygon.setNextControlPoint (p - 1, mapped);
178 continue;
179 } else if (((i - last_normal) % 3) == 2) {
180 prev = mapped;
181 hasPrev = true;
182 continue;
184 } else
185 last_normal = i;
187 polygon.append (mapped);
188 if (hasPrev) {
189 polygon.setPrevControlPoint (p, prev);
190 hasPrev = false;
192 p ++;
193 if (pPointTypes && (pPointTypes [i] & 0x80)) { // closed polygon
194 polygon.setClosed (true);
195 aPolygon.append (polygon);
196 last_normal = i + 1;
197 p = 0;
198 polygon.clear ();
202 if (polygon.count ())
203 aPolygon.append (polygon);
205 return aPolygon;
209 struct EMFPRegion : public EMFPObject
211 sal_Int32 parts;
212 sal_Int32 *combineMode;
213 sal_Int32 initialState;
214 EMFPPath *initialPath;
215 float ix, iy, iw, ih;
217 EMFPRegion ()
219 combineMode = NULL;
220 initialPath = NULL;
223 ~EMFPRegion ()
225 if (combineMode) {
226 delete [] combineMode;
227 combineMode = NULL;
229 if (initialPath) {
230 delete initialPath;
231 initialPath = NULL;
235 void Read (SvStream& s)
237 sal_uInt32 header;
239 s >> header >> parts;
241 EMFP_DEBUG (printf ("EMF+\tregion\n"));
242 EMFP_DEBUG (printf ("EMF+\theader: 0x%08x parts: %d\n", header, parts));
244 if (parts) {
245 if( parts<0 || parts>SAL_MAX_INT32/sizeof(sal_Int32) )
246 parts = SAL_MAX_INT32/sizeof(sal_Int32);
248 combineMode = new sal_Int32 [parts];
250 for (int i = 0; i < parts; i ++) {
251 s >> combineMode [i];
252 EMFP_DEBUG (printf ("EMF+\tcombine mode [%d]: 0x%08x\n", i, combineMode [i]));
256 s >> initialState;
257 EMFP_DEBUG (printf ("EMF+\tinitial state: 0x%08x\n", initialState));
261 struct EMFPBrush : public EMFPObject
263 ::Color solidColor;
264 sal_uInt32 type;
265 sal_uInt32 additionalFlags;
267 /* linear gradient */
268 sal_Int32 wrapMode;
269 float areaX, areaY, areaWidth, areaHeight;
270 ::Color secondColor; // first color is stored in solidColor;
271 XForm transformation;
272 bool hasTransformation;
273 sal_Int32 blendPoints;
274 float* blendPositions;
275 float* blendFactors;
276 sal_Int32 colorblendPoints;
277 float* colorblendPositions;
278 ::Color* colorblendColors;
279 sal_Int32 surroundColorsNumber;
280 ::Color* surroundColors;
281 EMFPPath *path;
283 public:
284 EMFPBrush ()
286 blendPositions = NULL;
287 colorblendPositions = NULL;
288 colorblendColors = NULL;
289 surroundColors = NULL;
290 path = NULL;
291 hasTransformation = false;
294 ~EMFPBrush ()
296 if (blendPositions != NULL) {
297 delete[] blendPositions;
298 blendPositions = NULL;
300 if (colorblendPositions != NULL) {
301 delete[] colorblendPositions;
302 colorblendPositions = NULL;
304 if (colorblendColors != NULL) {
305 delete[] colorblendColors;
306 colorblendColors = NULL;
308 if (surroundColors != NULL) {
309 delete[] surroundColors;
310 surroundColors = NULL;
312 if (path) {
313 delete path;
314 path = NULL;
318 UINT32 GetType () { return type; }
319 const ::Color& GetColor () { return solidColor; }
321 void Read (SvStream& s, ImplRenderer& rR)
323 UINT32 header;
325 s >> header >> type;
327 EMFP_DEBUG (printf ("EMF+\tbrush\nEMF+\theader: 0x%08x type: %d\n", header, type));
329 switch (type) {
330 case 0:
332 UINT32 color;
334 s >> color;
335 solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
336 EMFP_DEBUG (printf ("EMF+\tsolid color: 0x%08x\n", color));
338 break;
340 // path gradient
341 case 3:
343 s >> additionalFlags >> wrapMode;
345 EMFP_DEBUG (printf ("EMF+\tpath gradient, additional flags: 0x%02x\n", additionalFlags));
347 UINT32 color;
349 s >> color;
350 solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
351 EMFP_DEBUG (printf ("EMF+\tcenter color: 0x%08x\n", color));
353 s >> areaX >> areaY;
354 EMFP_DEBUG (printf ("EMF+\tcenter point: %f,%f\n", areaX, areaY));
356 s >> surroundColorsNumber;
357 EMFP_DEBUG (printf ("EMF+\tsurround colors: %d\n", surroundColorsNumber));
359 if( surroundColorsNumber<0 || surroundColorsNumber>SAL_MAX_INT32/sizeof(::Color) )
360 surroundColorsNumber = SAL_MAX_INT32/sizeof(::Color);
362 surroundColors = new ::Color [surroundColorsNumber];
363 for (int i = 0; i < surroundColorsNumber; i++) {
364 s >> color;
365 surroundColors[i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
366 if (i == 0)
367 secondColor = surroundColors [0];
368 EMFP_DEBUG (printf ("EMF+\tsurround color[%d]: 0x%08x\n", i, color));
371 if (additionalFlags & 0x01) {
372 sal_Int32 pathLength;
374 s >> pathLength;
375 EMFP_DEBUG (printf ("EMF+\tpath length: %d\n", pathLength));
377 sal_uInt32 pos = s.Tell ();
378 EMFP_DEBUG (dumpWords (s, 32));
380 sal_uInt32 pathHeader;
381 sal_Int32 pathPoints, pathFlags;
382 s >> pathHeader >> pathPoints >> pathFlags;
384 EMFP_DEBUG (printf ("EMF+\tpath (brush path gradient)\n"));
385 EMFP_DEBUG (printf ("EMF+\theader: 0x%08x points: %d additional flags: 0x%08x\n", pathHeader, pathPoints, pathFlags));
387 path = new EMFPPath (pathPoints);
388 path->Read (s, pathFlags, rR);
390 s.Seek (pos + pathLength);
392 const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (path->GetPolygon (rR, false)));
393 areaWidth = aBounds.getWidth ();
394 areaHeight = aBounds.getHeight ();
396 EMFP_DEBUG (printf ("EMF+\tpolygon bounding box: %f,%f %fx%f\n", aBounds.getMinX (), aBounds.getMinY (), aBounds.getWidth (), aBounds.getHeight ()));
399 if (additionalFlags & 0x02) {
400 EMFP_DEBUG (printf ("EMF+\tuse transformation\n", color));
401 s >> transformation;
402 hasTransformation = true;
403 EMFP_DEBUG (printf ("EMF+\tm11: %f m12: %f\nEMF+\tm21: %f m22: %f\nEMF+\tdx: %f dy: %f\n",
404 transformation.eM11, transformation.eM12,
405 transformation.eM21, transformation.eM22,
406 transformation.eDx, transformation.eDy));
408 if (additionalFlags & 0x08) {
409 s >> blendPoints;
410 EMFP_DEBUG (printf ("EMF+\tuse blend, points: %d\n", blendPoints));
411 if( blendPoints<0 || blendPoints>SAL_MAX_INT32/(2*sizeof(float)) )
412 blendPoints = SAL_MAX_INT32/(2*sizeof(float));
413 blendPositions = new float [2*blendPoints];
414 blendFactors = blendPositions + blendPoints;
415 for (int i=0; i < blendPoints; i ++) {
416 s >> blendPositions [i];
417 EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i, blendPositions [i]));
419 for (int i=0; i < blendPoints; i ++) {
420 s >> blendFactors [i];
421 EMFP_DEBUG (printf ("EMF+\tfactor[%d]: %f\n", i, blendFactors [i]));
425 if (additionalFlags & 0x04) {
426 s >> colorblendPoints;
427 EMFP_DEBUG (printf ("EMF+\tuse color blend, points: %d\n", colorblendPoints));
428 if( colorblendPoints<0 || colorblendPoints>SAL_MAX_INT32/sizeof(float) )
429 colorblendPoints = SAL_MAX_INT32/sizeof(float);
430 if( colorblendPoints>SAL_MAX_INT32/sizeof(::Color) )
431 colorblendPoints = SAL_MAX_INT32/sizeof(::Color);
432 colorblendPositions = new float [colorblendPoints];
433 colorblendColors = new ::Color [colorblendPoints];
434 for (int i=0; i < colorblendPoints; i ++) {
435 s >> colorblendPositions [i];
436 EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i, colorblendPositions [i]));
438 for (int i=0; i < colorblendPoints; i ++) {
439 s >> color;
440 colorblendColors [i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
441 EMFP_DEBUG (printf ("EMF+\tcolor[%d]: 0x%08x\n", i, color));
444 } else
445 EMFP_DEBUG (dumpWords (s, 1024));
447 break;
449 // linear gradient
450 case 4:
452 s >> additionalFlags >> wrapMode;
454 EMFP_DEBUG (printf ("EMF+\tlinear gradient, additional flags: 0x%02x\n", additionalFlags));
456 s >> areaX >> areaY >> areaWidth >> areaHeight;
458 EMFP_DEBUG (printf ("EMF+\tarea: %f,%f - %fx%f\n", areaX, areaY, areaWidth, areaHeight));
460 UINT32 color;
462 s >> color;
463 solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
464 EMFP_DEBUG (printf ("EMF+\tfirst color: 0x%08x\n", color));
466 s >> color;
467 secondColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
468 EMFP_DEBUG (printf ("EMF+\tsecond color: 0x%08x\n", color));
470 // repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html
471 s >> color;
472 s >> color;
474 if (additionalFlags & 0x02) {
475 EMFP_DEBUG (printf ("EMF+\tuse transformation\n", color));
476 s >> transformation;
477 hasTransformation = true;
478 EMFP_DEBUG (printf ("EMF+\tm11: %f m12: %f\nEMF+\tm21: %f m22: %f\nEMF+\tdx: %f dy: %f\n",
479 transformation.eM11, transformation.eM12,
480 transformation.eM21, transformation.eM22,
481 transformation.eDx, transformation.eDy));
483 if (additionalFlags & 0x08) {
484 s >> blendPoints;
485 EMFP_DEBUG (printf ("EMF+\tuse blend, points: %d\n", blendPoints));
486 if( blendPoints<0 || blendPoints>SAL_MAX_INT32/(2*sizeof(float)) )
487 blendPoints = SAL_MAX_INT32/(2*sizeof(float));
488 blendPositions = new float [2*blendPoints];
489 blendFactors = blendPositions + blendPoints;
490 for (int i=0; i < blendPoints; i ++) {
491 s >> blendPositions [i];
492 EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i, blendPositions [i]));
494 for (int i=0; i < blendPoints; i ++) {
495 s >> blendFactors [i];
496 EMFP_DEBUG (printf ("EMF+\tfactor[%d]: %f\n", i, blendFactors [i]));
500 if (additionalFlags & 0x04) {
501 s >> colorblendPoints;
502 EMFP_DEBUG (printf ("EMF+\tuse color blend, points: %d\n", colorblendPoints));
503 if( colorblendPoints<0 || colorblendPoints>SAL_MAX_INT32/sizeof(float) )
504 colorblendPoints = SAL_MAX_INT32/sizeof(float);
505 if( colorblendPoints>SAL_MAX_INT32/sizeof(::Color) )
506 colorblendPoints = SAL_MAX_INT32/sizeof(::Color);
507 colorblendPositions = new float [colorblendPoints];
508 colorblendColors = new ::Color [colorblendPoints];
509 for (int i=0; i < colorblendPoints; i ++) {
510 s >> colorblendPositions [i];
511 EMFP_DEBUG (printf ("EMF+\tposition[%d]: %f\n", i, colorblendPositions [i]));
513 for (int i=0; i < colorblendPoints; i ++) {
514 s >> color;
515 colorblendColors [i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
516 EMFP_DEBUG (printf ("EMF+\tcolor[%d]: 0x%08x\n", i, color));
520 break;
522 default:
523 EMFP_DEBUG (printf ("EMF+\tunhandled brush type: %d\n", type));
528 struct EMFPPen : public EMFPBrush
530 XForm transformation;
531 float width;
532 sal_Int32 startCap;
533 sal_Int32 endCap;
534 sal_Int32 lineJoin;
535 float mitterLimit;
536 sal_Int32 dashStyle;
537 sal_Int32 dashCap;
538 float dashOffset;
539 sal_Int32 dashPatternLen;
540 float *dashPattern;
541 sal_Int32 alignment;
542 sal_Int32 compoundArrayLen;
543 float *compoundArray;
544 sal_Int32 customStartCapLen;
545 sal_uInt8 *customStartCap;
546 sal_Int32 customEndCapLen;
547 sal_uInt8 *customEndCap;
549 public:
550 EMFPPen () : EMFPBrush ()
554 void SetStrokeAttributes (rendering::StrokeAttributes& rStrokeAttributes, ImplRenderer& rR, const OutDevState& rState)
556 rStrokeAttributes.StrokeWidth = (rState.mapModeTransform * rR.MapSize (width, 0)).getX ();
559 void Read (SvStream& s, ImplRenderer& rR, sal_Int32 nHDPI, sal_Int32 nVDPI)
561 UINT32 header, unknown, penFlags, unknown2;
562 int i;
564 s >> header >> unknown >> penFlags >> unknown2 >> width;
566 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));
568 if (penFlags & 1)
569 s >> transformation;
571 if (penFlags & 2)
572 s >> startCap;
573 else
574 startCap = 0;
576 if (penFlags & 4)
577 s >> endCap;
578 else
579 endCap = 0;
581 if (penFlags & 8)
582 s >> lineJoin;
583 else
584 lineJoin = 0;
586 if (penFlags & 16)
587 s >> mitterLimit;
588 else
589 mitterLimit = 0;
591 if (penFlags & 32)
592 s >> dashStyle;
593 else
594 dashStyle = 0;
596 if (penFlags & 64)
597 s >> dashCap;
598 else
599 dashCap = 0;
601 if (penFlags & 128)
602 s >> dashOffset;
603 else
604 dashOffset = 0;
606 if (penFlags & 256) {
607 s >> dashPatternLen;
608 if( dashPatternLen<0 || dashPatternLen>SAL_MAX_INT32/sizeof(float) )
609 dashPatternLen = SAL_MAX_INT32/sizeof(float);
610 dashPattern = new float [dashPatternLen];
611 for (i = 0; i < dashPatternLen; i++)
612 s >> dashPattern [i];
613 } else
614 dashPatternLen = 0;
616 if (penFlags & 512)
617 s >> alignment;
618 else
619 alignment = 0;
621 if (penFlags & 1024) {
622 s >> compoundArrayLen;
623 if( compoundArrayLen<0 || compoundArrayLen>SAL_MAX_INT32/sizeof(float) )
624 compoundArrayLen = SAL_MAX_INT32/sizeof(float);
625 compoundArray = new float [compoundArrayLen];
626 for (i = 0; i < compoundArrayLen; i++)
627 s >> compoundArray [i];
628 } else
629 compoundArrayLen = 0;
631 if (penFlags & 2048) {
632 s >> customStartCapLen;
633 if( customStartCapLen<0 )
634 customStartCapLen=0;
635 customStartCap = new sal_uInt8 [customStartCapLen];
636 for (i = 0; i < customStartCapLen; i++)
637 s >> customStartCap [i];
638 } else
639 customStartCapLen = 0;
641 if (penFlags & 4096) {
642 s >> customEndCapLen;
643 if( customEndCapLen<0 )
644 customEndCapLen=0;
645 customEndCap = new sal_uInt8 [customEndCapLen];
646 for (i = 0; i < customEndCapLen; i++)
647 s >> customEndCap [i];
648 } else
649 customEndCapLen = 0;
651 EMFPBrush::Read (s, rR);
655 struct EMFPImage : public EMFPObject
657 sal_uInt32 type;
658 sal_Int32 width;
659 sal_Int32 height;
660 sal_Int32 stride;
661 sal_Int32 pixelFormat;
662 Graphic graphic;
665 void Read (SvMemoryStream &s)
667 sal_uInt32 header, unknown;
669 s >> header >> type;
671 EMFP_DEBUG (printf ("EMF+\timage\nEMF+\theader: 0x%08x type: 0x%08x\n", header, type));
673 if (type == 1) { // bitmap
674 s >> width >> height >> stride >> pixelFormat >> unknown;
675 EMFP_DEBUG (printf ("EMF+\tbitmap width: %d height: %d stride: %d pixelFormat: 0x%08x\n", width, height, stride, pixelFormat));
676 if (width == 0) { // non native formats
677 GraphicFilter filter;
679 filter.ImportGraphic (graphic, String (), s);
680 EMFP_DEBUG (printf ("EMF+\tbitmap width: %d height: %d\n", graphic.GetBitmap ().GetSizePixel ().Width (), graphic.GetBitmap ().GetSizePixel ().Height ()));
683 } else if (type == 2) {
684 sal_Int32 mfType, mfSize;
686 s >> mfType >> mfSize;
687 EMFP_DEBUG (printf ("EMF+\tmetafile type: %d dataSize: %d\n", mfType, mfSize));
689 GraphicFilter filter;
690 SvMemoryStream mfStream (((char *)s.GetData()) + s.Tell(), mfSize, STREAM_READ);
692 filter.ImportGraphic (graphic, String (), mfStream);
694 // debug code - write the stream to debug file /tmp/emf-stream.emf
695 EMFP_DEBUG(mfStream.Seek(0);
696 SvFileStream file( UniString::CreateFromAscii( "/tmp/emf-embedded-stream.emf" ), STREAM_WRITE | STREAM_TRUNC );
698 mfStream >> file;
699 file.Flush();
700 file.Close());
705 struct EMFPFont : public EMFPObject
707 sal_uInt32 version;
708 float emSize;
709 sal_uInt32 sizeUnit;
710 sal_Int32 fontFlags;
711 rtl::OUString family;
713 void Read (SvMemoryStream &s)
715 sal_uInt32 header;
716 sal_uInt32 reserved;
717 sal_uInt32 length;
719 s >> header >> emSize >> sizeUnit >> fontFlags >> reserved >> length;
721 OSL_ASSERT( ( header >> 12 ) == 0xdbc01 );
723 EMFP_DEBUG (printf ("EMF+\tfont\nEMF+\theader: 0x%08x version: 0x%08x size: %f unit: 0x%08x\n", header >> 12, header & 0x1fff, emSize, sizeUnit));
724 EMFP_DEBUG (printf ("EMF+\tflags: 0x%08x reserved: 0x%08x length: 0x%08x\n", fontFlags, reserved, length));
726 if( length > 0 && length < 0x4000 ) {
727 sal_Unicode chars[ length ];
729 for( int i = 0; i < length; i++ )
730 s >> chars[ i ];
732 family = ::rtl::OUString( chars, length );
733 EMFP_DEBUG (printf ("EMF+\tfamily: %s\n", rtl::OUStringToOString( family, RTL_TEXTENCODING_UTF8).getStr()));
738 void ImplRenderer::ReadRectangle (SvStream& s, float& x, float& y, float &width, float& height, sal_uInt32 flags)
740 if (flags & 0x4000) {
741 sal_Int16 ix, iy, iw, ih;
743 s >> ix >> iy >> iw >> ih;
745 x = ix;
746 y = iy;
747 width = iw;
748 height = ih;
749 } else
750 s >> x >> y >> width >> height;
753 void ImplRenderer::ReadPoint (SvStream& s, float& x, float& y, sal_uInt32 flags)
755 if (flags & 0x4000) {
756 sal_Int16 ix, iy;
758 s >> ix >> iy;
760 x = ix;
761 y = iy;
762 } else
763 s >> x >> y;
766 void ImplRenderer::MapToDevice (double& x, double& y)
768 // TODO: other untis
769 x = 100*nMmX*x/nPixX;
770 y = 100*nMmY*y/nPixY;
773 ::basegfx::B2DPoint ImplRenderer::Map (::basegfx::B2DPoint& p)
775 return Map (p.getX (), p.getY ());
778 ::basegfx::B2DPoint ImplRenderer::Map (double ix, double iy)
780 double x, y;
782 x = ix*aWorldTransform.eM11 + iy*aWorldTransform.eM21 + aWorldTransform.eDx;
783 y = ix*aWorldTransform.eM12 + iy*aWorldTransform.eM22 + aWorldTransform.eDy;
785 MapToDevice (x, y);
787 x -= nFrameLeft;
788 y -= nFrameTop;
790 x *= aBaseTransform.eM11;
791 y *= aBaseTransform.eM22;
793 return ::basegfx::B2DPoint (x, y);
796 ::basegfx::B2DSize ImplRenderer::MapSize (double iwidth, double iheight)
798 double w, h;
800 w = iwidth*aWorldTransform.eM11 + iheight*aWorldTransform.eM21;
801 h = iwidth*aWorldTransform.eM12 + iheight*aWorldTransform.eM22;
803 MapToDevice (w, h);
805 w *= aBaseTransform.eM11;
806 h *= aBaseTransform.eM22;
808 return ::basegfx::B2DSize (w, h);
811 ::basegfx::B2DRange ImplRenderer::MapRectangle (double ix, double iy, double iwidth, double iheight)
813 double x, y, w, h;
815 x = ix*aWorldTransform.eM11 + iy*aWorldTransform.eM21 + aWorldTransform.eDx;
816 y = ix*aWorldTransform.eM12 + iy*aWorldTransform.eM22 + aWorldTransform.eDy;
817 w = iwidth*aWorldTransform.eM11 + iheight*aWorldTransform.eM21;
818 h = iwidth*aWorldTransform.eM12 + iheight*aWorldTransform.eM22;
820 MapToDevice (x, y);
821 MapToDevice (w, h);
823 x -= nFrameLeft;
824 y -= nFrameTop;
826 x *= aBaseTransform.eM11;
827 y *= aBaseTransform.eM22;
828 w *= aBaseTransform.eM11;
829 h *= aBaseTransform.eM22;
831 return ::basegfx::B2DRange (x, y, x + w, y + h);
834 #define COLOR(x) \
835 ::vcl::unotools::colorToDoubleSequence( ::Color (0xff - (x >> 24), \
836 (x >> 16) & 0xff, \
837 (x >> 8) & 0xff, \
838 x & 0xff), \
839 rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace());
840 #define SET_FILL_COLOR(x) \
841 rState.fillColor = COLOR(x);
842 #define SET_LINE_COLOR(x) \
843 rState.lineColor = COLOR(x);
844 #define SET_TEXT_COLOR(x) \
845 rState.textColor = COLOR(x);
847 void ImplRenderer::EMFPPlusFillPolygon (::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms,
848 OutDevState& rState, const CanvasSharedPtr& rCanvas, bool isColor, sal_uInt32 brushIndexOrColor)
850 ::basegfx::B2DPolyPolygon localPolygon (polygon);
852 EMFP_DEBUG (printf ("EMF+\tfill polygon\n"));
854 localPolygon.transform( rState.mapModeTransform );
856 ActionSharedPtr pPolyAction;
858 if (isColor) {
859 EMFP_DEBUG (printf ("EMF+\t\tcolor fill\n"));
861 rState.isFillColorSet = true;
862 rState.isLineColorSet = false;
863 SET_FILL_COLOR(brushIndexOrColor);
865 pPolyAction = ActionSharedPtr ( internal::PolyPolyActionFactory::createPolyPolyAction( localPolygon, rParms.mrCanvas, rState ) );
867 } else {
868 rState.isFillColorSet = true;
869 // extract UseBrush
870 EMFPBrush* brush = (EMFPBrush*) aObjects [brushIndexOrColor];
871 EMFP_DEBUG (printf ("EMF+\tbrush fill slot: %d (type: %d)\n", brushIndexOrColor, brush->GetType ()));
873 // give up in case something wrong happened
874 if( !brush )
875 return;
877 rState.isFillColorSet = false;
878 rState.isLineColorSet = false;
880 if (brush->type == 3 || brush->type == 4) {
882 if (brush->type == 3 && !(brush->additionalFlags & 0x1))
883 return; // we are unable to parse these brushes yet
885 ::basegfx::B2DHomMatrix aTextureTransformation;
886 ::basegfx::B2DHomMatrix aWorldTransformation;
887 ::basegfx::B2DHomMatrix aBaseTransformation;
888 rendering::Texture aTexture;
889 double nRotation( 0.0 );
890 const ::basegfx::B2DRectangle aBounds( ::basegfx::tools::getRange( localPolygon ) );
891 const double nScale( ::basegfx::pruneScaleValue( fabs( aBounds.getHeight()*sin(nRotation) ) +
892 fabs( aBounds.getWidth()*cos(nRotation) )));
894 aWorldTransformation.set (0, 0, aWorldTransform.eM11);
895 aWorldTransformation.set (0, 1, aWorldTransform.eM21);
896 aWorldTransformation.set (0, 2, aWorldTransform.eDx);
897 aWorldTransformation.set (1, 0, aWorldTransform.eM12);
898 aWorldTransformation.set (1, 1, aWorldTransform.eM22);
899 aWorldTransformation.set (1, 2, aWorldTransform.eDy);
901 aBaseTransformation.set (0, 0, aBaseTransform.eM11);
902 aBaseTransformation.set (0, 1, aBaseTransform.eM21);
903 aBaseTransformation.set (0, 2, aBaseTransform.eDx);
904 aBaseTransformation.set (1, 0, aBaseTransform.eM12);
905 aBaseTransformation.set (1, 1, aBaseTransform.eM22);
906 aBaseTransformation.set (1, 2, aBaseTransform.eDy);
908 if (brush->type == 4) {
909 aTextureTransformation.scale (brush->areaWidth, brush->areaHeight);
910 aTextureTransformation.translate (brush->areaX, brush->areaY);
911 } else {
912 aTextureTransformation.translate (-0.5, -0.5);
913 aTextureTransformation.scale (brush->areaWidth, brush->areaHeight);
914 aTextureTransformation.translate (brush->areaX,brush->areaY);
917 if (brush->hasTransformation) {
918 ::basegfx::B2DHomMatrix aTransformation;
920 aTransformation.set (0, 0, brush->transformation.eM11);
921 aTransformation.set (0, 1, brush->transformation.eM21);
922 aTransformation.set (0, 2, brush->transformation.eDx);
923 aTransformation.set (1, 0, brush->transformation.eM12);
924 aTransformation.set (1, 1, brush->transformation.eM22);
925 aTransformation.set (1, 2, brush->transformation.eDy);
927 aTextureTransformation *= aTransformation;
930 aTextureTransformation *= aWorldTransformation;
931 aTextureTransformation.scale (100.0*nMmX/nPixX, 100.0*nMmY/nPixY);
932 aTextureTransformation.translate (-nFrameLeft, -nFrameTop);
933 aTextureTransformation *= rState.mapModeTransform;
934 aTextureTransformation *= aBaseTransformation;
936 aTexture.RepeatModeX = rendering::TexturingMode::CLAMP;
937 aTexture.RepeatModeY = rendering::TexturingMode::CLAMP;
938 aTexture.Alpha = 1.0;
940 uno::Reference< rendering::XParametricPolyPolygon2DFactory > xFactory(
941 rParms.mrCanvas->getUNOCanvas()->getDevice()->getParametricPolyPolygonFactory() );
943 if( xFactory.is() ) {
944 const uno::Sequence< double > aStartColor(
945 ::vcl::unotools::colorToDoubleSequence( brush->solidColor,
946 rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() ) );
947 const uno::Sequence< double > aEndColor(
948 ::vcl::unotools::colorToDoubleSequence( brush->secondColor,
949 rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() ) );
950 uno::Sequence< uno::Sequence < double > > aColors (2);
951 uno::Sequence< double > aStops (2);
953 if (brush->blendPositions) {
954 EMFP_DEBUG (printf ("EMF+\t\tuse blend\n"));
955 aColors.realloc (brush->blendPoints);
956 aStops.realloc (brush->blendPoints);
957 int length = aStartColor.getLength ();
958 uno::Sequence< double > aColor (length);
960 OSL_ASSERT (length == aEndColor.getLength());
962 for (int i = 0; i < brush->blendPoints; i++) {
963 aStops[i] = brush->blendPositions [i];
965 for (int j = 0; j < length; j++) {
966 if (brush->type == 4) {
967 // // gamma correction
968 // if (brush->additionalFlags & 0x80)
969 // aColor [j] = pow (aStartColor [j]*(1 - brush->blendFactors[i]) + aEndColor [j]*brush->blendFactors[i], 1/2.2);
970 // else
971 aColor [j] = aStartColor [j]*(1 - brush->blendFactors[i]) + aEndColor [j]*brush->blendFactors[i];
972 } else
973 aColor [j] = aStartColor [j]*brush->blendFactors[i] + aEndColor [j]*(1 - brush->blendFactors[i]);
976 aColors[i] = aColor;
978 } else if (brush->colorblendPositions) {
979 EMFP_DEBUG (printf ("EMF+\t\tuse color blend\n"));
980 aColors.realloc (brush->colorblendPoints);
981 aStops.realloc (brush->colorblendPoints);
983 for (int i = 0; i < brush->colorblendPoints; i++) {
984 aStops[i] = brush->colorblendPositions [i];
985 aColors[(brush->type == 4) ? i : brush->colorblendPoints - 1 - i] = ::vcl::unotools::colorToDoubleSequence( brush->colorblendColors [i],
986 rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
988 } else {
989 aStops[0] = 0.0;
990 aStops[1] = 1.0;
992 if (brush->type == 4) {
993 aColors[0] = aStartColor;
994 aColors[1] = aEndColor;
995 } else {
996 aColors[1] = aStartColor;
997 aColors[0] = aEndColor;
1001 EMFP_DEBUG (printf ("EMF+\t\tset gradient\n"));
1002 if (brush->type == 4)
1003 aTexture.Gradient = xFactory->createLinearHorizontalGradient( aColors,
1004 aStops );
1005 else {
1006 geometry::RealRectangle2D aBoundsRectangle (0, 0, 1, 1);
1007 aTexture.Gradient = xFactory->createEllipticalGradient( aColors,
1008 aStops,
1009 aBoundsRectangle);
1013 ::basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform,
1014 aTextureTransformation );
1016 pPolyAction =
1017 ActionSharedPtr ( internal::PolyPolyActionFactory::createPolyPolyAction( localPolygon,
1018 rParms.mrCanvas,
1019 rState,
1020 aTexture ) );
1024 if( pPolyAction )
1026 EMFP_DEBUG (printf ("EMF+\t\tadd poly action\n"));
1028 maActions.push_back(
1029 MtfAction(
1030 pPolyAction,
1031 rParms.mrCurrActionIndex ) );
1033 rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
1037 void ImplRenderer::processObjectRecord(SvMemoryStream& rObjectStream, UINT16 flags)
1039 UINT32 objectLen;
1040 sal_uInt32 index;
1042 EMFP_DEBUG (printf ("EMF+ Object slot: %hd flags: %hx\n", flags & 0xff, flags & 0xff00));
1044 index = flags & 0xff;
1045 if (aObjects [index] != NULL) {
1046 delete aObjects [index];
1047 aObjects [index] = NULL;
1050 switch (flags & 0x7f00) {
1051 case EmfPlusObjectTypeBrush:
1053 EMFPBrush *brush;
1054 aObjects [index] = brush = new EMFPBrush ();
1055 brush->Read (rObjectStream, *this);
1057 break;
1059 case EmfPlusObjectTypePen:
1061 EMFPPen *pen;
1062 aObjects [index] = pen = new EMFPPen ();
1063 pen->Read (rObjectStream, *this, nHDPI, nVDPI);
1065 break;
1067 case EmfPlusObjectTypePath:
1068 sal_uInt32 header, pathFlags;
1069 sal_Int32 points;
1071 rObjectStream >> header >> points >> pathFlags;
1073 EMFP_DEBUG (printf ("EMF+\tpath\n"));
1074 EMFP_DEBUG (printf ("EMF+\theader: 0x%08x points: %d additional flags: 0x%08x\n", header, points, pathFlags));
1076 EMFPPath *path;
1077 aObjects [index] = path = new EMFPPath (points);
1078 path->Read (rObjectStream, pathFlags, *this);
1080 break;
1081 case EmfPlusObjectTypeRegion: {
1082 EMFPRegion *region;
1084 aObjects [index] = region = new EMFPRegion ();
1085 region->Read (rObjectStream);
1087 break;
1089 case EmfPlusObjectTypeImage:
1091 EMFPImage *image;
1092 aObjects [index] = image = new EMFPImage ();
1093 image->Read (rObjectStream);
1095 break;
1097 case EmfPlusObjectTypeFont:
1099 EMFPFont *font;
1100 aObjects [index] = font = new EMFPFont ();
1101 font->Read (rObjectStream);
1103 break;
1105 default:
1106 EMFP_DEBUG (printf ("EMF+\tObject unhandled flags: 0x%04x\n", flags & 0xff00));
1107 break;
1111 void ImplRenderer::processEMFPlus( MetaCommentAction* pAct, const ActionFactoryParameters& rFactoryParms,
1112 OutDevState& rState, const CanvasSharedPtr& rCanvas )
1114 sal_uInt32 length = pAct->GetDataSize ();
1115 SvMemoryStream rMF ((void*) pAct->GetData (), length, STREAM_READ);
1117 length -= 4;
1119 while (length > 0) {
1120 UINT16 type, flags;
1121 UINT32 size, dataSize;
1122 sal_uInt32 next;
1124 rMF >> type >> flags >> size >> dataSize;
1126 next = rMF.Tell() + ( size - 12 );
1128 EMFP_DEBUG (printf ("EMF+ record size: %d type: %04hx flags: %04hx data size: %d\n", size, type, flags, dataSize));
1130 if (type == EmfPlusRecordTypeObject && (mbMultipart && flags & 0x7fff == mMFlags & 0x7fff || flags & 0x8000)) {
1131 if (!mbMultipart) {
1132 mbMultipart = true;
1133 mMFlags = flags;
1134 mMStream.Seek(0);
1137 // 1st 4 bytes are unknown
1138 mMStream.Write (((const char *)rMF.GetData()) + rMF.Tell() + 4, dataSize - 4);
1139 EMFP_DEBUG (printf ("EMF+ read next object part size: %d type: %04hx flags: %04hx data size: %d\n", size, type, flags, dataSize));
1140 } else {
1141 if (mbMultipart) {
1142 EMFP_DEBUG (printf ("EMF+ multipart record flags: %04hx\n", mMFlags));
1143 mMStream.Seek (0);
1144 processObjectRecord (mMStream, mMFlags);
1146 mbMultipart = false;
1149 if (type != EmfPlusRecordTypeObject || !(flags & 0x8000))
1150 switch (type) {
1151 case EmfPlusRecordTypeHeader:
1152 UINT32 header, version;
1154 rMF >> header >> version >> nHDPI >> nVDPI;
1156 EMFP_DEBUG (printf ("EMF+ Header\n"));
1157 EMFP_DEBUG (printf ("EMF+\theader: 0x%08x version: %d horizontal DPI: %d vertical DPI: %d dual: %d\n", header, version, nHDPI, nVDPI, flags & 1));
1159 break;
1160 case EmfPlusRecordTypeEndOfFile:
1161 EMFP_DEBUG (printf ("EMF+ EndOfFile\n"));
1162 break;
1163 case EmfPlusRecordTypeGetDC:
1164 EMFP_DEBUG (printf ("EMF+ GetDC\n"));
1165 EMFP_DEBUG (printf ("EMF+\talready used in svtools wmf/emf filter parser\n"));
1166 break;
1167 case EmfPlusRecordTypeObject:
1168 processObjectRecord (rMF, flags);
1169 break;
1170 case EmfPlusRecordTypeFillPath:
1172 sal_uInt32 index = flags & 0xff;
1173 sal_uInt32 brushIndexOrColor;
1175 rMF >> brushIndexOrColor;
1177 EMFP_DEBUG (printf ("EMF+ FillPath slot: %d\n", index));
1179 EMFPPlusFillPolygon (((EMFPPath*) aObjects [index])->GetPolygon (*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
1181 break;
1182 case EmfPlusRecordTypeFillRects:
1184 EMFP_DEBUG (printf ("EMF+ FillRects\n"));
1186 sal_uInt32 brushIndexOrColor;
1187 sal_Int32 rectangles;
1188 ::basegfx::B2DPolygon polygon;
1190 rMF >> brushIndexOrColor >> rectangles;
1192 EMFP_DEBUG (printf ("EMF+\t%s: 0x%08x\n", (flags & 0x8000) ? "color" : "brush index", brushIndexOrColor));
1194 for (int i=0; i < rectangles; i++) {
1195 if (flags & 0x4000) {
1196 /* 16bit integers */
1197 sal_Int16 x, y, width, height;
1199 rMF >> x >> y >> width >> height;
1201 polygon.append (Map (x, y));
1202 polygon.append (Map (x + width, y));
1203 polygon.append (Map (x + width, y + height));
1204 polygon.append (Map (x, y + height));
1206 EMFP_DEBUG (printf ("EMF+\trectangle: %d,%d %dx%d\n", x, y, width, height));
1207 } else {
1208 /* Single's */
1209 float x, y, width, height;
1211 rMF >> x >> y >> width >> height;
1213 polygon.append (Map (x, y));
1214 polygon.append (Map (x + width, y));
1215 polygon.append (Map (x + width, y + height));
1216 polygon.append (Map (x, y + height));
1218 EMFP_DEBUG (printf ("EMF+\trectangle: %f,%f %fx%f\n", x, y, width, height));
1221 ::basegfx::B2DPolyPolygon polyPolygon (polygon);
1223 EMFPPlusFillPolygon (polyPolygon, rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
1225 break;
1227 case EmfPlusRecordTypeFillPolygon:
1229 sal_uInt8 index = flags & 0xff;
1230 sal_uInt32 brushIndexOrColor;
1231 sal_Int32 brushIndex;
1232 sal_Int32 points;
1233 UINT32 color;
1234 USHORT transparency = 0;
1236 rMF >> brushIndexOrColor;
1237 rMF >> points;
1239 EMFP_DEBUG (printf ("EMF+ FillPolygon in slot: %d points: %d\n", index, points));
1240 EMFP_DEBUG (printf ("EMF+\twith solid color (ARGB): 0x%08X\n", color));
1242 EMFPPath path (points, true);
1243 path.Read (rMF, flags, *this);
1246 EMFPPlusFillPolygon (path.GetPolygon (*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor);
1248 break;
1250 case EmfPlusRecordTypeDrawLines:
1252 sal_uInt32 index = flags & 0xff;
1253 sal_uInt32 points;
1255 rMF >> points;
1257 EMFP_DEBUG (printf ("EMF+ DrawLines in slot: %d points: %d\n", index, points));
1259 EMFPPath path (points, true);
1260 path.Read (rMF, flags, *this);
1262 EMFPPen* pen = (EMFPPen*) aObjects [index];
1264 rState.isFillColorSet = false;
1265 rState.isLineColorSet = true;
1266 rState.lineColor = ::vcl::unotools::colorToDoubleSequence (pen->GetColor (),
1267 rCanvas->getUNOCanvas ()->getDevice()->getDeviceColorSpace() );
1268 ::basegfx::B2DPolyPolygon& polygon (path.GetPolygon (*this));
1270 polygon.transform( rState.mapModeTransform );
1272 rendering::StrokeAttributes aStrokeAttributes;
1274 pen->SetStrokeAttributes (aStrokeAttributes, *this, rState);
1276 ActionSharedPtr pPolyAction(
1277 internal::PolyPolyActionFactory::createPolyPolyAction(
1278 polygon, rFactoryParms.mrCanvas, rState, aStrokeAttributes ) );
1280 if( pPolyAction )
1282 maActions.push_back(
1283 MtfAction(
1284 pPolyAction,
1285 rFactoryParms.mrCurrActionIndex ) );
1287 rFactoryParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
1290 break;
1292 case EmfPlusRecordTypeDrawPath:
1294 UINT32 penIndex;
1296 rMF >> penIndex;
1298 EMFP_DEBUG (printf ("EMF+ DrawPath\n"));
1299 EMFP_DEBUG (printf ("EMF+\tpen: %d\n", penIndex));
1301 EMFPPath* path = (EMFPPath*) aObjects [flags & 0xff];
1302 EMFPPen* pen = (EMFPPen*) aObjects [penIndex];
1304 rState.isFillColorSet = false;
1305 rState.isLineColorSet = true;
1306 rState.lineColor = ::vcl::unotools::colorToDoubleSequence (pen->GetColor (),
1307 rCanvas->getUNOCanvas ()->getDevice()->getDeviceColorSpace());
1308 ::basegfx::B2DPolyPolygon& polygon (path->GetPolygon (*this));
1310 polygon.transform( rState.mapModeTransform );
1311 rendering::StrokeAttributes aStrokeAttributes;
1313 pen->SetStrokeAttributes (aStrokeAttributes, *this, rState);
1315 ActionSharedPtr pPolyAction(
1316 internal::PolyPolyActionFactory::createPolyPolyAction(
1317 polygon, rFactoryParms.mrCanvas, rState, aStrokeAttributes ) );
1319 if( pPolyAction )
1321 maActions.push_back(
1322 MtfAction(
1323 pPolyAction,
1324 rFactoryParms.mrCurrActionIndex ) );
1326 rFactoryParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
1328 break;
1330 case EmfPlusRecordTypeDrawImagePoints:
1332 sal_uInt32 attrIndex;
1333 sal_Int32 sourceUnit;
1335 rMF >> attrIndex >> sourceUnit;
1337 EMFP_DEBUG (printf ("EMF+ DrawImagePoints attributes index: %d source unit: %d\n", attrIndex, sourceUnit));
1338 EMFP_DEBUG (printf ("EMF+\tTODO: use image attributes\n"));
1340 if (sourceUnit == 2 && aObjects [flags & 0xff]) { // we handle only GraphicsUnit.Pixel now
1341 EMFPImage& image = *(EMFPImage *) aObjects [flags & 0xff];
1342 float sx, sy, sw, sh;
1343 sal_Int32 unknown;
1345 ReadRectangle (rMF, sx, sy, sw, sh);
1347 rMF >> unknown;
1349 EMFP_DEBUG (printf ("EMF+ DrawImagePoints source rectangle: %f,%f %fx%f unknown: 0x%08x\n", sx, sy, sw, sh, unknown));
1351 if (unknown == 3) { // it probably means number of points defining destination rectangle
1352 float x1, y1, x2, y2, x3, y3;
1354 ReadPoint (rMF, x1, y1);
1355 ReadPoint (rMF, x2, y2);
1356 ReadPoint (rMF, x3, y3);
1358 BitmapEx aBmp( image.graphic.GetBitmapEx () );
1359 const Rectangle aCropRect (::vcl::unotools::pointFromB2DPoint (Map (sx, sy)),
1360 ::vcl::unotools::sizeFromB2DSize (MapSize(sw, sh)));
1361 aBmp.Crop( aCropRect );
1364 ActionSharedPtr pBmpAction (
1365 internal::BitmapActionFactory::createBitmapAction (
1366 aBmp,
1367 rState.mapModeTransform * Map (x1, y1),
1368 rState.mapModeTransform * MapSize(x2 - x1, y3 - y1),
1369 rCanvas,
1370 rState));
1372 if( pBmpAction ) {
1373 maActions.push_back( MtfAction( pBmpAction,
1374 rFactoryParms.mrCurrActionIndex ) );
1376 rFactoryParms.mrCurrActionIndex += pBmpAction->getActionCount()-1;
1378 } else
1379 EMFP_DEBUG (printf ("EMF+ DrawImagePoints TODO (fixme)\n"));
1381 break;
1383 case EmfPlusRecordTypeDrawString:
1384 EMFP_DEBUG (printf ("EMF+ DrawString\n"));
1385 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1386 break;
1387 case EmfPlusRecordTypeSetPageTransform:
1388 rMF >> fPageScale;
1390 EMFP_DEBUG (printf ("EMF+ SetPageTransform\n"));
1391 EMFP_DEBUG (printf ("EMF+\tscale: %f unit: %d\n", fPageScale, flags));
1392 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1393 break;
1394 case EmfPlusRecordTypeSetRenderingOrigin:
1395 rMF >> nOriginX >> nOriginY;
1396 EMFP_DEBUG (printf ("EMF+ SetRenderingOrigin\n"));
1397 EMFP_DEBUG (printf ("EMF+\torigin [x,y]: %d,%d\n", nOriginX, nOriginY));
1398 break;
1399 case EmfPlusRecordTypeSetTextRenderingHint:
1400 EMFP_DEBUG (printf ("EMF+ SetTextRenderingHint\n"));
1401 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1402 break;
1403 case EmfPlusRecordTypeSetAntiAliasMode:
1404 EMFP_DEBUG (printf ("EMF+ SetAntiAliasMode\n"));
1405 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1406 break;
1407 case EmfPlusRecordTypeSetInterpolationMode:
1408 EMFP_DEBUG (printf ("EMF+ InterpolationMode\n"));
1409 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1410 break;
1411 case EmfPlusRecordTypeSetPixelOffsetMode:
1412 EMFP_DEBUG (printf ("EMF+ SetPixelOffsetMode\n"));
1413 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1414 break;
1415 case EmfPlusRecordTypeSetCompositingQuality:
1416 EMFP_DEBUG (printf ("EMF+ SetCompositingQuality\n"));
1417 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1418 break;
1419 case EmfPlusRecordTypeSave:
1420 EMFP_DEBUG (printf ("EMF+ Save\n"));
1421 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1422 break;
1423 case EmfPlusRecordTypeSetWorldTransform: {
1424 EMFP_DEBUG (printf ("EMF+ SetWorldTransform\n"));
1425 XForm transform;
1426 rMF >> transform;
1427 aWorldTransform.Set (transform);
1428 EMFP_DEBUG (printf ("EMF+\tm11: %f m12: %f\nEMF+\tm21: %f m22: %f\nEMF+\tdx: %f dy: %f\n",
1429 aWorldTransform.eM11, aWorldTransform.eM12,
1430 aWorldTransform.eM21, aWorldTransform.eM22,
1431 aWorldTransform.eDx, aWorldTransform.eDy));
1432 break;
1434 case EmfPlusRecordTypeResetWorldTransform:
1435 EMFP_DEBUG (printf ("EMF+ ResetWorldTransform\n"));
1436 aWorldTransform.SetIdentity ();
1437 break;
1438 case EmfPlusRecordTypeSetClipPath:
1440 EMFP_DEBUG (printf ("EMF+ SetClipPath\n"));
1441 EMFP_DEBUG (printf ("EMF+\tpath in slot: %d\n", flags & 0xff));
1443 EMFPPath& path = *(EMFPPath*) aObjects [flags & 0xff];
1444 ::basegfx::B2DPolyPolygon& clipPoly (path.GetPolygon (*this));
1446 clipPoly.transform (rState.mapModeTransform);
1447 updateClipping (clipPoly, rFactoryParms, false);
1449 break;
1451 case EmfPlusRecordTypeSetClipRegion: {
1452 EMFP_DEBUG (printf ("EMF+ SetClipRegion\n"));
1453 EMFP_DEBUG (printf ("EMF+\tregion in slot: %d combine mode: %d\n", flags & 0xff, (flags & 0xff00) >> 8));
1454 EMFPRegion& region = *(EMFPRegion*) aObjects [flags & 0xff];
1456 // reset clip
1457 if (region.parts == 0 && region.initialState == EmfPlusRegionInitialStateInfinite) {
1458 updateClipping (::basegfx::B2DPolyPolygon (), rFactoryParms, false);
1459 } else
1460 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1461 break;
1463 case EmfPlusRecordTypeDrawDriverString: {
1464 EMFP_DEBUG (printf ("EMF+ DrawDriverString, flags: 0x%04x\n", flags));
1465 sal_uInt32 brushIndexOrColor;
1466 sal_uInt32 optionFlags;
1467 sal_uInt32 hasMatrix;
1468 sal_uInt32 glyphsCount;
1470 rMF >> brushIndexOrColor >> optionFlags >> hasMatrix >> glyphsCount;
1472 EMFP_DEBUG (printf ("EMF+\t%s: 0x%08x\n", (flags & 0x8000) ? "color" : "brush index", brushIndexOrColor));
1473 EMFP_DEBUG (printf ("EMF+\toption flags: 0x%08x\n", optionFlags));
1474 EMFP_DEBUG (printf ("EMF+\thas matrix: %d\n", hasMatrix));
1475 EMFP_DEBUG (printf ("EMF+\tglyphs: %d\n", glyphsCount));
1477 if( ( optionFlags & 1 ) && glyphsCount > 0 ) {
1478 sal_uInt16 chars[ glyphsCount ];
1479 float charsPosX[ glyphsCount ];
1480 float charsPosY[ glyphsCount ];
1482 for( int i=0; i<glyphsCount; i++) {
1483 rMF >> chars[i];
1484 EMFP_DEBUG (printf ("EMF+\tglyph[%d]: 0x%04x\n",
1485 i, chars[i]));
1487 for( int i=0; i<glyphsCount; i++) {
1488 rMF >> charsPosX[i] >> charsPosY[i];
1489 EMFP_DEBUG (printf ("EMF+\tglyphPosition[%d]: %f, %f\n", i, charsPosX[i], charsPosY[i]));
1492 XForm transform;
1493 if( hasMatrix ) {
1494 rMF >> transform;
1495 EMFP_DEBUG (printf ("EMF+\tmatrix:: %f, %f, %f, %f, %f, %f\n", transform.eM11, transform.eM12, transform.eM21, transform.eM22, transform.eDx, transform.eDy));
1498 // create and add the text action
1499 XubString text( chars, glyphsCount );
1501 EMFPFont *font = (EMFPFont*) aObjects[ flags & 0xff ];
1503 rendering::FontRequest aFontRequest;
1504 aFontRequest.FontDescription.FamilyName = font->family;
1505 aFontRequest.CellSize = (rState.mapModeTransform*MapSize( font->emSize, 0 )).getX();
1506 rState.xFont = rFactoryParms.mrCanvas->getUNOCanvas()->createFont( aFontRequest,
1507 uno::Sequence< beans::PropertyValue >(),
1508 geometry::Matrix2D() );
1509 if( flags & 0x8000 )
1510 SET_TEXT_COLOR(brushIndexOrColor);
1512 ActionSharedPtr pTextAction(
1513 TextActionFactory::createTextAction(
1514 ::vcl::unotools::pointFromB2DPoint ( Map( charsPosX[0], charsPosY[0] ) ),
1515 ::Size(),
1516 ::Color(),
1517 ::Size(),
1518 ::Color(),
1519 text,
1521 glyphsCount,
1522 NULL,
1523 rFactoryParms.mrVDev,
1524 rFactoryParms.mrCanvas,
1525 rState,
1526 rFactoryParms.mrParms,
1527 false ) );
1529 if( pTextAction )
1531 EMFP_DEBUG (printf ("EMF+\t\tadd text action\n"));
1533 maActions.push_back(
1534 MtfAction(
1535 pTextAction,
1536 rFactoryParms.mrCurrActionIndex ) );
1538 rFactoryParms.mrCurrActionIndex += pTextAction->getActionCount()-1;
1540 } else {
1541 EMFP_DEBUG (printf ("EMF+\tTODO: fonts (non-unicode glyphs chars)\n"));
1544 break;
1546 default:
1547 EMFP_DEBUG (printf ("EMF+ unhandled record type: %d\n", type));
1548 EMFP_DEBUG (printf ("EMF+\tTODO\n"));
1551 rMF.Seek (next);
1553 length -= size;