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