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