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 2000, 2010 Oracle and/or its affiliates.
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 <drawinglayer/processor2d/vclmetafileprocessor2d.hxx>
30 : : #include <tools/gen.hxx>
31 : : #include <vcl/virdev.hxx>
32 : : #include <vcl/gdimtf.hxx>
33 : : #include <vcl/gradient.hxx>
34 : : #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
35 : : #include <drawinglayer/primitive2d/textprimitive2d.hxx>
36 : : #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
37 : : #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
38 : : #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
39 : : #include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx>
40 : : #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
41 : : #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
42 : : #include <basegfx/polygon/b2dpolygonclipper.hxx>
43 : : #include <basegfx/polygon/b2dpolypolygontools.hxx>
44 : : #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
45 : : #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
46 : : #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
47 : : #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
48 : : #include <drawinglayer/processor2d/vclpixelprocessor2d.hxx>
49 : : #include <tools/stream.hxx>
50 : : #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
51 : : #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
52 : : #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
53 : : #include <vcl/graphictools.hxx>
54 : : #include <vcl/metaact.hxx>
55 : : #include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
56 : : #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
57 : : #include <comphelper/processfactory.hxx>
58 : : #include <rtl/ustring.hxx>
59 : : #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
60 : : #include <com/sun/star/i18n/WordType.hpp>
61 : : #include <drawinglayer/primitive2d/controlprimitive2d.hxx>
62 : : #include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
63 : : #include <basegfx/polygon/b2dpolygontools.hxx>
64 : : #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
65 : : #include <helperchartrenderer.hxx>
66 : : #include <drawinglayer/primitive2d/epsprimitive2d.hxx>
67 : : #include <basegfx/polygon/b2dlinegeometry.hxx>
68 : :
69 : : //////////////////////////////////////////////////////////////////////////////
70 : : // for PDFExtOutDevData Graphic support
71 : :
72 : : #include <vcl/graph.hxx>
73 : : #include <vcl/svapp.hxx>
74 : : #include <toolkit/helper/formpdfexport.hxx>
75 : :
76 : : //////////////////////////////////////////////////////////////////////////////
77 : : // for Control printing
78 : :
79 : : #include <com/sun/star/beans/XPropertySet.hpp>
80 : :
81 : : //////////////////////////////////////////////////////////////////////////////
82 : : // for current chart PrettyPrinting support
83 : :
84 : : #include <drawinglayer/primitive2d/chartprimitive2d.hxx>
85 : :
86 : : //////////////////////////////////////////////////////////////////////////////
87 : : // for StructureTagPrimitive support in sd's unomodel.cxx
88 : :
89 : : #include <drawinglayer/primitive2d/structuretagprimitive2d.hxx>
90 : :
91 : : //////////////////////////////////////////////////////////////////////////////
92 : :
93 : : using namespace com::sun::star;
94 : :
95 : : //////////////////////////////////////////////////////////////////////////////
96 : : // #112245# definition for maximum allowed point count due to Metafile target.
97 : : // To be on the safe side with the old tools polygon, use slightly less then
98 : : // the theoretical maximum (bad experiences with tools polygon)
99 : :
100 : : #define MAX_POLYGON_POINT_COUNT_METAFILE (0x0000fff0)
101 : :
102 : : //////////////////////////////////////////////////////////////////////////////
103 : :
104 : : namespace
105 : : {
106 : : // #112245# helper to split line polygon in half
107 : 0 : void splitLinePolygon(
108 : : const basegfx::B2DPolygon& rBasePolygon,
109 : : basegfx::B2DPolygon& o_aLeft,
110 : : basegfx::B2DPolygon& o_aRight)
111 : : {
112 : 0 : const sal_uInt32 nCount(rBasePolygon.count());
113 : :
114 [ # # ]: 0 : if(nCount)
115 : : {
116 : 0 : const sal_uInt32 nHalfCount((nCount - 1) >> 1);
117 : :
118 [ # # ]: 0 : o_aLeft = basegfx::B2DPolygon(rBasePolygon, 0, nHalfCount + 1);
119 : 0 : o_aLeft.setClosed(false);
120 : :
121 [ # # ]: 0 : o_aRight = basegfx::B2DPolygon(rBasePolygon, nHalfCount, nCount - nHalfCount);
122 : 0 : o_aRight.setClosed(false);
123 : :
124 [ # # ]: 0 : if(rBasePolygon.isClosed())
125 : : {
126 [ # # ]: 0 : o_aRight.append(rBasePolygon.getB2DPoint(0));
127 : :
128 [ # # ]: 0 : if(rBasePolygon.areControlPointsUsed())
129 : : {
130 : : o_aRight.setControlPoints(
131 [ # # ]: 0 : o_aRight.count() - 1,
132 : : rBasePolygon.getPrevControlPoint(0),
133 [ # # ][ # # ]: 0 : rBasePolygon.getNextControlPoint(0));
134 : : }
135 : : }
136 : : }
137 : : else
138 : : {
139 : 0 : o_aLeft.clear();
140 : 0 : o_aRight.clear();
141 : : }
142 : 0 : }
143 : :
144 : : // #112245# helper to evtl. split filled polygons to maximum metafile point count
145 : 1195 : bool fillPolyPolygonNeededToBeSplit(basegfx::B2DPolyPolygon& rPolyPolygon)
146 : : {
147 : 1195 : bool bRetval(false);
148 : 1195 : const sal_uInt32 nPolyCount(rPolyPolygon.count());
149 : :
150 [ + - ]: 1195 : if(nPolyCount)
151 : : {
152 [ + - ]: 1195 : basegfx::B2DPolyPolygon aSplitted;
153 : :
154 [ + + ]: 2390 : for(sal_uInt32 a(0); a < nPolyCount; a++)
155 : : {
156 [ + - ]: 1195 : const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a));
157 [ + - ]: 1195 : const sal_uInt32 nPointCount(aCandidate.count());
158 : 1195 : bool bNeedToSplit(false);
159 : :
160 [ + - ][ - + ]: 1195 : if(aCandidate.areControlPointsUsed())
161 : : {
162 : : // compare with the maximum for bezier curved polygons
163 : 0 : bNeedToSplit = nPointCount > ((MAX_POLYGON_POINT_COUNT_METAFILE / 3L) - 1L);
164 : : }
165 : : else
166 : : {
167 : : // compare with the maximum for simple point polygons
168 : 1195 : bNeedToSplit = nPointCount > (MAX_POLYGON_POINT_COUNT_METAFILE - 1);
169 : : }
170 : :
171 [ - + ]: 1195 : if(bNeedToSplit)
172 : : {
173 : : // need to split the partial polygon
174 [ # # ]: 0 : const basegfx::B2DRange aRange(aCandidate.getB2DRange());
175 [ # # ]: 0 : const basegfx::B2DPoint aCenter(aRange.getCenter());
176 : :
177 [ # # ][ # # ]: 0 : if(aRange.getWidth() > aRange.getHeight())
[ # # ]
178 : : {
179 : : // clip in left and right
180 : : const basegfx::B2DPolyPolygon aLeft(
181 : : basegfx::tools::clipPolygonOnParallelAxis(
182 : : aCandidate,
183 : : false,
184 : : true,
185 : : aCenter.getX(),
186 [ # # ]: 0 : false));
187 : : const basegfx::B2DPolyPolygon aRight(
188 : : basegfx::tools::clipPolygonOnParallelAxis(
189 : : aCandidate,
190 : : false,
191 : : false,
192 : : aCenter.getX(),
193 [ # # ]: 0 : false));
194 : :
195 [ # # ]: 0 : aSplitted.append(aLeft);
196 [ # # ][ # # ]: 0 : aSplitted.append(aRight);
[ # # ]
197 : : }
198 : : else
199 : : {
200 : : // clip in top and bottom
201 : : const basegfx::B2DPolyPolygon aTop(
202 : : basegfx::tools::clipPolygonOnParallelAxis(
203 : : aCandidate,
204 : : true,
205 : : true,
206 : : aCenter.getY(),
207 [ # # ]: 0 : false));
208 : : const basegfx::B2DPolyPolygon aBottom(
209 : : basegfx::tools::clipPolygonOnParallelAxis(
210 : : aCandidate,
211 : : true,
212 : : false,
213 : : aCenter.getY(),
214 [ # # ]: 0 : false));
215 : :
216 [ # # ]: 0 : aSplitted.append(aTop);
217 [ # # ][ # # ]: 0 : aSplitted.append(aBottom);
[ # # ]
218 : 0 : }
219 : : }
220 : : else
221 : : {
222 [ + - ]: 1195 : aSplitted.append(aCandidate);
223 : : }
224 [ + - ]: 1195 : }
225 : :
226 [ + - ][ - + ]: 1195 : if(aSplitted.count() != nPolyCount)
227 : : {
228 [ # # ]: 0 : rPolyPolygon = aSplitted;
229 [ + - ]: 1195 : }
230 : : }
231 : :
232 : 1195 : return bRetval;
233 : : }
234 : :
235 : : /** Filter input polypolygon for effectively empty sub-fills
236 : :
237 : : Needed to fix fdo#37559
238 : :
239 : : @param rPoly
240 : : PolyPolygon to filter
241 : :
242 : : @return converted tools PolyPolygon, w/o one-point fills
243 : : */
244 : 1195 : PolyPolygon getFillPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly )
245 : : {
246 : : // filter input rPoly
247 [ + - ]: 1195 : basegfx::B2DPolyPolygon aPoly;
248 [ + - ]: 1195 : sal_uInt32 nCount(rPoly.count());
249 [ + + ]: 2390 : for( sal_uInt32 i=0; i<nCount; ++i )
250 : : {
251 [ + - ]: 1195 : basegfx::B2DPolygon aCandidate(rPoly.getB2DPolygon(i));
252 [ + - ][ + - ]: 1195 : if( !aCandidate.isClosed() || aCandidate.count() > 1 )
[ + - ][ + - ]
[ + - ]
253 [ + - ]: 1195 : aPoly.append(aCandidate);
254 [ + - ]: 1195 : }
255 [ + - ][ + - ]: 1195 : return PolyPolygon(aPoly);
256 : : }
257 : :
258 : : } // end of anonymous namespace
259 : :
260 : : //////////////////////////////////////////////////////////////////////////////
261 : :
262 : : namespace drawinglayer
263 : : {
264 : : namespace processor2d
265 : : {
266 : 0 : Rectangle VclMetafileProcessor2D::impDumpToMetaFile(
267 : : const primitive2d::Primitive2DSequence& rContent,
268 : : GDIMetaFile& o_rContentMetafile)
269 : : {
270 : : // Prepare VDev, MetaFile and connections
271 : 0 : OutputDevice* pLastOutputDevice = mpOutputDevice;
272 : 0 : GDIMetaFile* pLastMetafile = mpMetaFile;
273 [ # # ]: 0 : basegfx::B2DRange aPrimitiveRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
274 : :
275 : : // transform primitive range with current transformation (e.g shadow offset)
276 [ # # ]: 0 : aPrimitiveRange.transform(maCurrentTransformation);
277 : :
278 : : const Rectangle aPrimitiveRectangle(
279 : : basegfx::fround(aPrimitiveRange.getMinX()), basegfx::fround(aPrimitiveRange.getMinY()),
280 [ # # ][ # # ]: 0 : basegfx::fround(aPrimitiveRange.getMaxX()), basegfx::fround(aPrimitiveRange.getMaxY()));
[ # # ][ # # ]
[ # # ]
281 [ # # ]: 0 : VirtualDevice aContentVDev;
282 [ # # ]: 0 : MapMode aNewMapMode(pLastOutputDevice->GetMapMode());
283 : :
284 : 0 : mpOutputDevice = &aContentVDev;
285 : 0 : mpMetaFile = &o_rContentMetafile;
286 [ # # ]: 0 : aContentVDev.EnableOutput(false);
287 [ # # ]: 0 : aContentVDev.SetMapMode(pLastOutputDevice->GetMapMode());
288 [ # # ]: 0 : o_rContentMetafile.Record(&aContentVDev);
289 [ # # ]: 0 : aContentVDev.SetLineColor(pLastOutputDevice->GetLineColor());
290 [ # # ]: 0 : aContentVDev.SetFillColor(pLastOutputDevice->GetFillColor());
291 [ # # ]: 0 : aContentVDev.SetFont(pLastOutputDevice->GetFont());
292 [ # # ]: 0 : aContentVDev.SetDrawMode(pLastOutputDevice->GetDrawMode());
293 [ # # ]: 0 : aContentVDev.SetSettings(pLastOutputDevice->GetSettings());
294 [ # # ]: 0 : aContentVDev.SetRefPoint(pLastOutputDevice->GetRefPoint());
295 : :
296 : : // dump to MetaFile
297 [ # # ]: 0 : process(rContent);
298 : :
299 : : // cleanups
300 [ # # ]: 0 : o_rContentMetafile.Stop();
301 [ # # ]: 0 : o_rContentMetafile.WindStart();
302 [ # # ]: 0 : aNewMapMode.SetOrigin(aPrimitiveRectangle.TopLeft());
303 [ # # ]: 0 : o_rContentMetafile.SetPrefMapMode(aNewMapMode);
304 [ # # ]: 0 : o_rContentMetafile.SetPrefSize(aPrimitiveRectangle.GetSize());
305 : 0 : mpOutputDevice = pLastOutputDevice;
306 : 0 : mpMetaFile = pLastMetafile;
307 : :
308 [ # # ][ # # ]: 0 : return aPrimitiveRectangle;
309 : : }
310 : :
311 : 0 : void VclMetafileProcessor2D::impConvertFillGradientAttributeToVCLGradient(
312 : : Gradient& o_rVCLGradient,
313 : : const attribute::FillGradientAttribute& rFiGrAtt,
314 : : bool bIsTransparenceGradient)
315 : : {
316 [ # # ]: 0 : if(bIsTransparenceGradient)
317 : : {
318 : : // it's about transparence channel intensities (black/white), do not use color modifier
319 [ # # ]: 0 : o_rVCLGradient.SetStartColor(Color(rFiGrAtt.getStartColor()));
320 [ # # ]: 0 : o_rVCLGradient.SetEndColor(Color(rFiGrAtt.getEndColor()));
321 : : }
322 : : else
323 : : {
324 : : // use color modifier to influence start/end color of gradient
325 [ # # ]: 0 : o_rVCLGradient.SetStartColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getStartColor())));
326 [ # # ]: 0 : o_rVCLGradient.SetEndColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getEndColor())));
327 : : }
328 : :
329 : 0 : o_rVCLGradient.SetAngle(static_cast< sal_uInt16 >(rFiGrAtt.getAngle() * (1.0 / F_PI1800)));
330 : 0 : o_rVCLGradient.SetBorder(static_cast< sal_uInt16 >(rFiGrAtt.getBorder() * 100.0));
331 : 0 : o_rVCLGradient.SetOfsX(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetX() * 100.0));
332 : 0 : o_rVCLGradient.SetOfsY(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetY() * 100.0));
333 : 0 : o_rVCLGradient.SetSteps(rFiGrAtt.getSteps());
334 : :
335 : : // defaults for intensity; those were computed into the start/end colors already
336 : 0 : o_rVCLGradient.SetStartIntensity(100);
337 : 0 : o_rVCLGradient.SetEndIntensity(100);
338 : :
339 [ # # # # : 0 : switch(rFiGrAtt.getStyle())
# # ]
340 : : {
341 : : default : // attribute::GRADIENTSTYLE_LINEAR :
342 : : {
343 : 0 : o_rVCLGradient.SetStyle(GradientStyle_LINEAR);
344 : 0 : break;
345 : : }
346 : : case attribute::GRADIENTSTYLE_AXIAL :
347 : : {
348 : 0 : o_rVCLGradient.SetStyle(GradientStyle_AXIAL);
349 : 0 : break;
350 : : }
351 : : case attribute::GRADIENTSTYLE_RADIAL :
352 : : {
353 : 0 : o_rVCLGradient.SetStyle(GradientStyle_RADIAL);
354 : 0 : break;
355 : : }
356 : : case attribute::GRADIENTSTYLE_ELLIPTICAL :
357 : : {
358 : 0 : o_rVCLGradient.SetStyle(GradientStyle_ELLIPTICAL);
359 : 0 : break;
360 : : }
361 : : case attribute::GRADIENTSTYLE_SQUARE :
362 : : {
363 : 0 : o_rVCLGradient.SetStyle(GradientStyle_SQUARE);
364 : 0 : break;
365 : : }
366 : : case attribute::GRADIENTSTYLE_RECT :
367 : : {
368 : 0 : o_rVCLGradient.SetStyle(GradientStyle_RECT);
369 : 0 : break;
370 : : }
371 : : }
372 : 0 : }
373 : :
374 : 1195 : void VclMetafileProcessor2D::impStartSvtGraphicFill(SvtGraphicFill* pSvtGraphicFill)
375 : : {
376 [ + - ][ + - ]: 1195 : if(pSvtGraphicFill && !mnSvtGraphicFillCount)
377 : : {
378 [ + - ]: 1195 : SvMemoryStream aMemStm;
379 : :
380 [ + - ]: 1195 : aMemStm << *pSvtGraphicFill;
381 [ + - ][ + - ]: 1195 : mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_BEGIN", 0, static_cast< const sal_uInt8* >(aMemStm.GetData()), aMemStm.Seek(STREAM_SEEK_TO_END)));
[ + - ][ + - ]
[ + - ]
382 [ + - ]: 1195 : mnSvtGraphicFillCount++;
383 : : }
384 : 1195 : }
385 : :
386 : 1195 : void VclMetafileProcessor2D::impEndSvtGraphicFill(SvtGraphicFill* pSvtGraphicFill)
387 : : {
388 [ + - ][ + - ]: 1195 : if(pSvtGraphicFill && mnSvtGraphicFillCount)
389 : : {
390 : 1195 : mnSvtGraphicFillCount--;
391 [ + - ][ + - ]: 1195 : mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_END"));
[ + - ]
392 [ + - ]: 1195 : delete pSvtGraphicFill;
393 : : }
394 : 1195 : }
395 : :
396 : 11246 : SvtGraphicStroke* VclMetafileProcessor2D::impTryToCreateSvtGraphicStroke(
397 : : const basegfx::B2DPolygon& rB2DPolygon,
398 : : const basegfx::BColor* pColor,
399 : : const attribute::LineAttribute* pLineAttribute,
400 : : const attribute::StrokeAttribute* pStrokeAttribute,
401 : : const attribute::LineStartEndAttribute* pStart,
402 : : const attribute::LineStartEndAttribute* pEnd)
403 : : {
404 : 11246 : SvtGraphicStroke* pRetval = 0;
405 : :
406 [ + - ][ + + ]: 11246 : if(rB2DPolygon.count() && !mnSvtGraphicStrokeCount)
[ + + ]
407 : : {
408 : 4735 : basegfx::BColor aStrokeColor;
409 [ + - ]: 4735 : basegfx::B2DPolyPolygon aStartArrow;
410 [ + - ]: 4735 : basegfx::B2DPolyPolygon aEndArrow;
411 : :
412 [ - + ]: 4735 : if(pColor)
413 : : {
414 [ # # ]: 0 : aStrokeColor = *pColor;
415 : : }
416 [ + - ]: 4735 : else if(pLineAttribute)
417 : : {
418 [ + - ][ + - ]: 4735 : aStrokeColor = maBColorModifierStack.getModifiedColor(pLineAttribute->getColor());
[ + - ]
419 : : }
420 : :
421 : : // It IS needed to record the stroke color at all in the metafile,
422 : : // SvtGraphicStroke has NO entry for stroke color(!)
423 [ + - ]: 4735 : mpOutputDevice->SetLineColor(Color(aStrokeColor));
424 : :
425 [ + - ][ + + ]: 4735 : if(!rB2DPolygon.isClosed())
426 : : {
427 : 4440 : double fPolyLength(0.0);
428 : :
429 [ + + ][ + - ]: 4440 : if(pStart && pStart->isActive())
[ - + ][ - + ]
430 : : {
431 [ # # ]: 0 : fPolyLength = basegfx::tools::getLength(rB2DPolygon);
432 : :
433 : : aStartArrow = basegfx::tools::createAreaGeometryForLineStartEnd(
434 [ # # ]: 0 : rB2DPolygon, pStart->getB2DPolyPolygon(), true, pStart->getWidth(),
435 [ # # ][ # # ]: 0 : fPolyLength, pStart->isCentered() ? 0.5 : 0.0, 0);
[ # # ][ # # ]
[ # # ][ # # ]
436 : : }
437 : :
438 [ + + ][ + - ]: 4440 : if(pEnd && pEnd->isActive())
[ + - ][ + + ]
439 : : {
440 [ + - ]: 3 : if(basegfx::fTools::equalZero(fPolyLength))
441 : : {
442 [ + - ]: 3 : fPolyLength = basegfx::tools::getLength(rB2DPolygon);
443 : : }
444 : :
445 : : aEndArrow = basegfx::tools::createAreaGeometryForLineStartEnd(
446 [ + - ]: 3 : rB2DPolygon, pEnd->getB2DPolyPolygon(), false, pEnd->getWidth(),
447 [ + - ][ - + ]: 4443 : fPolyLength, pEnd->isCentered() ? 0.5 : 0.0, 0);
[ + - ][ + - ]
[ + - ][ + - ]
448 : : }
449 : : }
450 : :
451 : 4735 : SvtGraphicStroke::JoinType eJoin(SvtGraphicStroke::joinNone);
452 : 4735 : double fLineWidth(0.0);
453 : 4735 : double fMiterLength(0.0);
454 [ + - ]: 4735 : SvtGraphicStroke::DashArray aDashArray;
455 : :
456 [ + - ]: 4735 : if(pLineAttribute)
457 : : {
458 : : // pre-fill fLineWidth
459 [ + - ]: 4735 : fLineWidth = pLineAttribute->getWidth();
460 : :
461 : : // pre-fill fMiterLength
462 : 4735 : fMiterLength = fLineWidth;
463 : :
464 : : // get Join
465 [ + - ]: 4735 : switch(pLineAttribute->getLineJoin())
[ - - - + ]
466 : : {
467 : : default : // basegfx::B2DLINEJOIN_NONE :
468 : : {
469 : 0 : eJoin = SvtGraphicStroke::joinNone;
470 : 0 : break;
471 : : }
472 : : case basegfx::B2DLINEJOIN_BEVEL :
473 : : {
474 : 0 : eJoin = SvtGraphicStroke::joinBevel;
475 : 0 : break;
476 : : }
477 : : case basegfx::B2DLINEJOIN_MIDDLE :
478 : : case basegfx::B2DLINEJOIN_MITER :
479 : : {
480 : 0 : eJoin = SvtGraphicStroke::joinMiter;
481 : : // ATM 15 degrees is assumed
482 : 0 : fMiterLength /= rtl::math::sin(M_PI * (15.0 / 360.0));
483 : 0 : break;
484 : : }
485 : : case basegfx::B2DLINEJOIN_ROUND :
486 : : {
487 : 4735 : eJoin = SvtGraphicStroke::joinRound;
488 : 4735 : break;
489 : : }
490 : : }
491 : : }
492 : :
493 [ + - ]: 4735 : if(pStrokeAttribute)
494 : : {
495 : : // copy dash array
496 [ + - ][ + - ]: 4735 : aDashArray = pStrokeAttribute->getDotDashArray();
497 : : }
498 : :
499 : : // #i101734# apply current object transformation to created geometry.
500 : : // This is a partial fix. When a object transformation is used which
501 : : // e.g. contains a scaleX != scaleY, an unproportional scaling would
502 : : // have to be applied to the evtl. existing fat line. The current
503 : : // concept of PDF export and SvtGraphicStroke usage does simply not
504 : : // allow handling such definitions. The only clean way would be to
505 : : // add the transformation to SvtGraphicStroke and to handle it there
506 [ + - ]: 4735 : basegfx::B2DPolygon aB2DPolygon(rB2DPolygon);
507 : :
508 [ + - ]: 4735 : aB2DPolygon.transform(maCurrentTransformation);
509 [ + - ]: 4735 : aStartArrow.transform(maCurrentTransformation);
510 [ + - ]: 4735 : aEndArrow.transform(maCurrentTransformation);
511 : :
512 : : pRetval = new SvtGraphicStroke(
513 : : Polygon(aB2DPolygon),
514 : : PolyPolygon(aStartArrow),
515 : : PolyPolygon(aEndArrow),
516 : : mfCurrentUnifiedTransparence,
517 : : fLineWidth,
518 : : SvtGraphicStroke::capButt,
519 : : eJoin,
520 : : fMiterLength,
521 [ + - ][ + - ]: 4735 : aDashArray);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
522 : : }
523 : :
524 : 11246 : return pRetval;
525 : : }
526 : :
527 : 11246 : void VclMetafileProcessor2D::impStartSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke)
528 : : {
529 [ + + ][ + - ]: 11246 : if(pSvtGraphicStroke && !mnSvtGraphicStrokeCount)
530 : : {
531 [ + - ]: 4735 : SvMemoryStream aMemStm;
532 : :
533 [ + - ]: 4735 : aMemStm << *pSvtGraphicStroke;
534 [ + - ][ + - ]: 4735 : mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_BEGIN", 0, static_cast< const sal_uInt8* >(aMemStm.GetData()), aMemStm.Seek(STREAM_SEEK_TO_END)));
[ + - ][ + - ]
[ + - ]
535 [ + - ]: 4735 : mnSvtGraphicStrokeCount++;
536 : : }
537 : 11246 : }
538 : :
539 : 11246 : void VclMetafileProcessor2D::impEndSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke)
540 : : {
541 [ + + ][ + - ]: 11246 : if(pSvtGraphicStroke && mnSvtGraphicStrokeCount)
542 : : {
543 : 4735 : mnSvtGraphicStrokeCount--;
544 [ + - ][ + - ]: 4735 : mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_END"));
[ + - ]
545 [ + - ]: 4735 : delete pSvtGraphicStroke;
546 : : }
547 : 11246 : }
548 : :
549 : : // init static break iterator
550 : 245 : uno::Reference< ::com::sun::star::i18n::XBreakIterator > VclMetafileProcessor2D::mxBreakIterator;
551 : :
552 : 145 : VclMetafileProcessor2D::VclMetafileProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev)
553 : : : VclProcessor2D(rViewInformation, rOutDev),
554 : 145 : mpMetaFile(rOutDev.GetConnectMetaFile()),
555 : : mnSvtGraphicFillCount(0),
556 : : mnSvtGraphicStrokeCount(0),
557 : : mfCurrentUnifiedTransparence(0.0),
558 [ + - + - ]: 290 : mpPDFExtOutDevData(dynamic_cast< vcl::PDFExtOutDevData* >(rOutDev.GetExtOutDevData()))
559 : : {
560 : : OSL_ENSURE(rOutDev.GetConnectMetaFile(), "VclMetafileProcessor2D: Used on OutDev which has no MetaFile Target (!)");
561 : : // draw to logic coordinates, do not initialize maCurrentTransformation to viewTransformation
562 : : // but only to ObjectTransformation. Do not change MapMode of destination.
563 [ + - ][ + - ]: 145 : maCurrentTransformation = rViewInformation.getObjectTransformation();
564 : 145 : }
565 : :
566 [ + - ]: 145 : VclMetafileProcessor2D::~VclMetafileProcessor2D()
567 : : {
568 : : // MapMode was not changed, no restore necessary
569 [ - + ]: 290 : }
570 : :
571 : : /***********************************************************************************************
572 : :
573 : : Support of MetaCommentActions in the VclMetafileProcessor2D
574 : : Found MetaCommentActions and how they are supported:
575 : :
576 : : XGRAD_SEQ_BEGIN, XGRAD_SEQ_END:
577 : :
578 : : Used inside OutputDevice::DrawGradient to mark the start and end of a MetaGradientEx action.
579 : : It is used in various exporters/importers to have direct access to the gradient before it
580 : : is rendered by VCL (and thus fragmented to polygon color actions and others). On that base, e.g.
581 : : the Metafile to SdrObject import creates it's gradient objects.
582 : : Best (and safest) way to support it here is to use PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
583 : : map it back to the corresponding tools PolyPolygon and the Gradient and just call
584 : : OutputDevice::DrawGradient which creates the necessary compatible actions.
585 : :
586 : : XPATHFILL_SEQ_BEGIN, XPATHFILL_SEQ_END:
587 : :
588 : : Two producers, one is vcl/source/gdi/gdimtf.cxx, line 1273. There, it is transformed
589 : : inside GDIMetaFile::Rotate, nothing to take care of here.
590 : : The second producer is in graphics/svx/source/svdraw/impgrfll.cxx, line 374. This is used
591 : : with each incarnation of Imp_GraphicFill when a metafile is recorded, fillstyle is not
592 : : XFILL_NONE and not completely transparent. It creates a SvtGraphicFill and streams it
593 : : to the comment action. A closing end token is created in the destructor.
594 : : Usages of Imp_GraphicFill are in Do_Paint_Object-methods of SdrCircObj, SdrPathObj and
595 : : SdrRectObj.
596 : : The token users pick various actions from SvtGraphicFill, so it may need to be added for all kind
597 : : of filled objects, even simple colored polygons. It is added as extra information; the
598 : : Metafile actions between the two tokens are interpreted as output generated from those
599 : : fills. Thus, users have the choice to use the SvtGraphicFill info or the created output
600 : : actions.
601 : : Even for XFillTransparenceItem it is used, thus it may need to be supported in
602 : : UnifiedTransparencePrimitive2D, too, when interpreted as normally filled PolyPolygon.
603 : : Implemented for:
604 : : PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D,
605 : : PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D,
606 : : PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
607 : : PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D,
608 : : and for PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D when detected unified transparence
609 : :
610 : : XPATHSTROKE_SEQ_BEGIN, XPATHSTROKE_SEQ_END:
611 : :
612 : : Similar to pathfill, but using SvtGraphicStroke instead. It also has two producers where one
613 : : is also the GDIMetaFile::Rotate. Another user is MetaCommentAction::Move which modifies the
614 : : contained path accordingly.
615 : : The other one is SdrObject::Imp_DrawLineGeometry. It's done when MetaFile is set at OutDev and
616 : : only when geometry is a single polygon (!). I see no reason for that; in the PS exporter this
617 : : would hinder to make use of PolyPolygon strokes. I will need to add support at:
618 : : PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D
619 : : PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D
620 : : PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D
621 : : This can be done hierarchical, too.
622 : : Okay, base implementation done based on those three primitives.
623 : :
624 : : FIELD_SEQ_BEGIN, FIELD_SEQ_END
625 : :
626 : : Used from slideshow for URLs, created from diverse SvxField implementations inside
627 : : createBeginComment()/createEndComment(). createBeginComment() is used from editeng\impedit3.cxx
628 : : inside ImpEditEngine::Paint.
629 : : Created TextHierarchyFieldPrimitive2D and added needed infos there; it is an group primitive and wraps
630 : : text primitives (but is not limited to that). It contains the field type if special actions for the
631 : : support of FIELD_SEQ_BEGIN/END are needed; this is the case for Page and URL fields. If more is
632 : : needed, it may be supported there.
633 : : FIELD_SEQ_BEGIN;PageField
634 : : FIELD_SEQ_END
635 : : Okay, these are now completely supported by TextHierarchyFieldPrimitive2D. URL works, too.
636 : :
637 : : XTEXT
638 : :
639 : : XTEXT_EOC(i) end of character
640 : : XTEXT_EOW(i) end of word
641 : : XTEXT_EOS(i) end of sentence
642 : :
643 : : this three are with index and are created with the help of a i18n::XBreakIterator in
644 : : ImplDrawWithComments. Simplifying, moving out text painting, reworking to create some
645 : : data structure for holding those TEXT infos.
646 : : Supported directly by TextSimplePortionPrimitive2D with adding a Locale to the basic text
647 : : primitive. In the MetaFileRenderer, the creation is now done (see below). This has the advantage
648 : : that this creations do not need to be done for all paints all the time. This would be
649 : : expensive since the BreakIterator and it's usage is expensive and for each paint also the
650 : : whole character stops would need to be created.
651 : : Created only for TextDecoratedPortionPrimitive2D due to XTEXT_EOL and XTEXT_EOP (see below)
652 : :
653 : : XTEXT_EOL() end of line
654 : : XTEXT_EOP() end of paragraph
655 : :
656 : : First try with boolean marks at TextDecoratedPortionPrimitive2D did not work too well,
657 : : i decided to solve it with structure. I added the TextHierarchyPrimitives for this,
658 : : namely:
659 : : - TextHierarchyLinePrimitive2D: Encapsulates single line
660 : : - TextHierarchyParagraphPrimitive2D: Encapsulates single paragraph
661 : : - TextHierarchyBlockPrimitive2D: encapsulates object texts (only one ATM)
662 : : Those are now supported in hierarchy. This means the MetaFile renderer will support them
663 : : by using them, reculrively using their content and adding MetaFile comments as needed.
664 : : This also means that when another text layouter will be used it will be necessary to
665 : : create/support the same HierarchyPrimitives to support users.
666 : : To transport the information using this hierarchy is best suited to all future needs;
667 : : the slideshow will be able to profit from it directly when using primitives; all other
668 : : renderers not interested in the text structure will just ignore the encapsulations.
669 : :
670 : : XTEXT_PAINTSHAPE_BEGIN, XTEXT_PAINTSHAPE_END
671 : : Supported now by the TextHierarchyBlockPrimitive2D.
672 : :
673 : : EPSReplacementGraphic:
674 : : Only used in goodies\source\filter.vcl\ieps\ieps.cxx and svx\source\xml\xmlgrhlp.cxx to
675 : : hold the original EPS which was imported in the same MetaFile as first 2 entries. Only
676 : : used to export the original again (if exists).
677 : : Not necessary to support with MetaFuleRenderer.
678 : :
679 : : XTEXT_SCROLLRECT, XTEXT_PAINTRECT
680 : : Currently used to get extra MetaFile infos using GraphicExporter which again uses
681 : : SdrTextObj::GetTextScrollMetaFileAndRectangle(). ATM works with primitives since
682 : : the rectangle data is added directly by the GraphicsExporter as comment. Does not need
683 : : to be adapted at once.
684 : : When adapting later, the only user - the diashow - should directly use the provided
685 : : Anination infos in the appropriate primitives (e.g. AnimatedSwitchPrimitive2D)
686 : :
687 : : PRNSPOOL_TRANSPARENTBITMAP_BEGIN, PRNSPOOL_TRANSPARENTBITMAP_END
688 : : VCL usage when printing PL -> THB. Okay, THB confirms that it is only used as
689 : : a fix (hack) while VCL printing. It is needed to not downscale a bitmap which
690 : : was explicitly created for the printer already again to some default maximum
691 : : bitmap sizes.
692 : : Nothing to do here for the primitive renderer.
693 : :
694 : : Support for vcl::PDFExtOutDevData:
695 : : PL knows that SJ did that stuff, it's used to hold a pointer to PDFExtOutDevData at
696 : : the OutDev. When set, some extra data is written there. Trying simple PDF export and
697 : : watching if i get those infos.
698 : : Well, a PDF export does not use e.g. ImpEditEngine::Paint since the PdfFilter uses
699 : : the SdXImpressDocument::render and thus uses the VclMetafileProcessor2D. I will check
700 : : if i get a PDFExtOutDevData at the target output device.
701 : : Indeed, i get one. Checking what all may be done when that extra-device-info is there.
702 : :
703 : : All in all i have to talk to SJ. I will need to emulate some of those actions, but
704 : : i need to discuss which ones.
705 : : In the future, all those infos would be taken from the primitive sequence anyways,
706 : : thus these extensions would potentially be temporary, too.
707 : : Discussed with SJ, added the necessary support and tested it. Details follow.
708 : :
709 : : - In ImpEditEngine::Paint, paragraph infos and URL stuff is added.
710 : : Added in primitive MetaFile renderer.
711 : : Checking URL: Indeed, current version exports it, but it is missing in primitive
712 : : CWS version. Adding support.
713 : : Okay, URLs work. Checked, Done.
714 : :
715 : : - UnoControlPDFExportContact is only created when PDFExtOutDevData is used at the
716 : : target and uno control data is created in UnoControlPDFExportContact::do_PaintObject.
717 : : This may be added in primitive MetaFile renderer.
718 : : Adding support...
719 : : OOps, the necessary helper stuff is in svx/source/form/formpdxexport.cxx in namespace
720 : : svxform. Have to talk to FS if this has to be like that. Especially since
721 : : ::vcl::PDFWriter::AnyWidget is filled out, which is already part of vcl.
722 : : Wrote an eMail to FS, he is on vacation currently. I see no reason why not to move
723 : : that stuff to somewhere else, maybe tools or svtools ?!? We will see...
724 : : Moved to toolkit, so i have to link against it. I tried VCL first, but it did
725 : : not work since VCLUnoHelper::CreateFont is unresolved in VCL (!). Other then the name
726 : : may imply, it is defined in toolkit (!). Since toolkit is linked against VCL itself,
727 : : the lowest move,ment plave is toolkit.
728 : : Checked form control export, it works well. Done.
729 : :
730 : : - In goodies, in GraphicObject::Draw, when the used Graphic is linked, infos are
731 : : generated. I will need to check what happens here with primitives.
732 : : To support, use of GraphicPrimitive2D (PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D) may be needed.
733 : : Added support, but feature is broken in main version, so i cannot test at all.
734 : : Writing a bug to CL (or SJ) and seeing what happens (#i80380#).
735 : : SJ took a look and we got it working. Tested VCL MetaFile Renderer based export,
736 : : as intended, the original file is exported. Works, Done.
737 : :
738 : :
739 : :
740 : :
741 : : To be done:
742 : :
743 : : - Maybe there are more places to take care of for vcl::PDFExtOutDevData!
744 : :
745 : :
746 : :
747 : : ****************************************************************************************************/
748 : :
749 : 49334 : void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
750 : : {
751 [ - + + + : 49334 : switch(rCandidate.getPrimitive2DID())
+ - + + +
+ + + + -
- - - + -
- - + - -
- - - - -
- - + ]
752 : : {
753 : : case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
754 : : {
755 : : // directdraw of wrong spell primitive
756 : : // Ignore for VclMetafileProcessor2D, this is for printing and MetaFile recording only
757 : 0 : break;
758 : : }
759 : : case PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D :
760 : : {
761 : 12 : const primitive2d::GraphicPrimitive2D& rGraphicPrimitive = static_cast< const primitive2d::GraphicPrimitive2D& >(rCandidate);
762 : 12 : bool bUsingPDFExtOutDevData(false);
763 : 12 : basegfx::B2DVector aTranslate, aScale;
764 : : static bool bSuppressPDFExtOutDevDataSupport(false);
765 : :
766 [ # # ][ - + ]: 12 : if(mpPDFExtOutDevData && !bSuppressPDFExtOutDevDataSupport)
767 : : {
768 : : // emulate data handling from UnoControlPDFExportContact, original see
769 : : // svtools/source/graphic/grfmgr.cxx
770 [ # # ]: 0 : const Graphic& rGraphic = rGraphicPrimitive.getGraphicObject().GetGraphic();
771 : :
772 [ # # ][ # # ]: 0 : if(rGraphic.IsLink())
773 : : {
774 : 0 : const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
775 : :
776 [ # # ][ # # ]: 0 : if(!rAttr.IsSpecialDrawMode() && !rAttr.IsAdjusted())
[ # # ]
777 : : {
778 : 0 : const basegfx::B2DHomMatrix& rTransform = rGraphicPrimitive.getTransform();
779 : : double fRotate, fShearX;
780 [ # # ]: 0 : rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
781 : :
782 [ # # ][ # # ]: 0 : if( basegfx::fTools::equalZero( fRotate ) && ( aScale.getX() > 0.0 ) && ( aScale.getY() > 0.0 ) )
[ # # ][ # # ]
783 : : {
784 : 0 : bUsingPDFExtOutDevData = true;
785 [ # # ]: 0 : mpPDFExtOutDevData->BeginGroup();
786 : : }
787 : : }
788 : : }
789 : : }
790 : :
791 : : // process recursively and add MetaFile comment
792 [ + - ][ + - ]: 12 : process(rGraphicPrimitive.get2DDecomposition(getViewInformation2D()));
[ + - ]
793 : :
794 [ - + ]: 12 : if(bUsingPDFExtOutDevData)
795 : : {
796 : : // emulate data handling from UnoControlPDFExportContact, original see
797 : : // svtools/source/graphic/grfmgr.cxx
798 : : const basegfx::B2DRange aCurrentRange(
799 : : aTranslate.getX(), aTranslate.getY(),
800 [ # # ]: 0 : aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
801 : : const Rectangle aCurrentRect(
802 [ # # ][ # # ]: 0 : sal_Int32(floor(aCurrentRange.getMinX())), sal_Int32(floor(aCurrentRange.getMinY())),
803 [ # # ][ # # ]: 0 : sal_Int32(ceil(aCurrentRange.getMaxX())), sal_Int32(ceil(aCurrentRange.getMaxY())));
[ # # ]
804 : 0 : const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
805 [ # # ]: 0 : Rectangle aCropRect;
806 : :
807 [ # # ]: 0 : if(rAttr.IsCropped())
808 : : {
809 : : // calculate scalings between real image size and logic object size. This
810 : : // is necessary since the crop values are relative to original bitmap size
811 : 0 : double fFactorX(1.0);
812 : 0 : double fFactorY(1.0);
813 : :
814 : : {
815 [ # # ]: 0 : const MapMode aMapMode100thmm(MAP_100TH_MM);
816 [ # # ]: 0 : const Size aBitmapSize(Application::GetDefaultDevice()->LogicToLogic(
817 : 0 : rGraphicPrimitive.getGraphicObject().GetPrefSize(),
818 [ # # ]: 0 : rGraphicPrimitive.getGraphicObject().GetPrefMapMode(), aMapMode100thmm));
819 : 0 : const double fDivX(aBitmapSize.Width() - rAttr.GetLeftCrop() - rAttr.GetRightCrop());
820 : 0 : const double fDivY(aBitmapSize.Height() - rAttr.GetTopCrop() - rAttr.GetBottomCrop());
821 : :
822 [ # # ]: 0 : if(!basegfx::fTools::equalZero(fDivX))
823 : : {
824 : 0 : fFactorX = aScale.getX() / fDivX;
825 : : }
826 : :
827 [ # # ]: 0 : if(!basegfx::fTools::equalZero(fDivY))
828 : : {
829 : 0 : fFactorY = aScale.getY() / fDivY;
830 [ # # ]: 0 : }
831 : : }
832 : :
833 : : // calculate crop range and rect
834 [ # # ]: 0 : basegfx::B2DRange aCropRange;
835 [ # # ][ # # ]: 0 : aCropRange.expand(aCurrentRange.getMinimum() - basegfx::B2DPoint(rAttr.GetLeftCrop() * fFactorX, rAttr.GetTopCrop() * fFactorY));
836 [ # # ][ # # ]: 0 : aCropRange.expand(aCurrentRange.getMaximum() + basegfx::B2DPoint(rAttr.GetRightCrop() * fFactorX, rAttr.GetBottomCrop() * fFactorY));
837 : :
838 : : aCropRect = Rectangle(
839 [ # # ][ # # ]: 0 : sal_Int32(floor(aCropRange.getMinX())), sal_Int32(floor(aCropRange.getMinY())),
840 [ # # ][ # # ]: 0 : sal_Int32(ceil(aCropRange.getMaxX())), sal_Int32(ceil(aCropRange.getMaxY())));
[ # # ]
841 : : }
842 : :
843 [ # # ]: 0 : mpPDFExtOutDevData->EndGroup(rGraphicPrimitive.getGraphicObject().GetGraphic(),
844 : 0 : rAttr.GetTransparency(),
845 : : aCurrentRect,
846 [ # # ]: 0 : aCropRect);
847 : : }
848 : :
849 : 12 : break;
850 : : }
851 : : case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
852 : : {
853 : 3 : const primitive2d::ControlPrimitive2D& rControlPrimitive = static_cast< const primitive2d::ControlPrimitive2D& >(rCandidate);
854 [ + - ]: 3 : const uno::Reference< awt::XControl >& rXControl(rControlPrimitive.getXControl());
855 : 3 : bool bIsPrintableControl(false);
856 : :
857 : : // find out if control is printable
858 [ + - ]: 3 : if(rXControl.is())
859 : : {
860 : : try
861 : : {
862 [ + - ][ + - ]: 3 : uno::Reference< beans::XPropertySet > xModelProperties(rXControl->getModel(), uno::UNO_QUERY);
[ + - ]
863 : 3 : uno::Reference< beans::XPropertySetInfo > xPropertyInfo(xModelProperties.is()
864 [ + - ]: 3 : ? xModelProperties->getPropertySetInfo()
865 [ + - ][ + - ]: 6 : : uno::Reference< beans::XPropertySetInfo >());
866 : 3 : const ::rtl::OUString sPrintablePropertyName("Printable");
867 : :
868 [ + - ][ + - ]: 3 : if(xPropertyInfo.is() && xPropertyInfo->hasPropertyByName(sPrintablePropertyName))
[ + - ][ + - ]
[ + - ]
869 : : {
870 [ + - ][ + - ]: 3 : OSL_VERIFY(xModelProperties->getPropertyValue(sPrintablePropertyName) >>= bIsPrintableControl);
871 [ # # ]: 3 : }
872 : : }
873 [ # # ]: 0 : catch(const uno::Exception&)
874 : : {
875 : : OSL_FAIL("VclMetafileProcessor2D: No access to printable flag of Control, caught an exception!");
876 : : }
877 : : }
878 : :
879 : : // PDF export and printing only for printable controls
880 [ + - ]: 3 : if(bIsPrintableControl)
881 : : {
882 [ - + ][ # # ]: 3 : const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields());
[ # # ]
883 : 3 : bool bDoProcessRecursively(true);
884 : :
885 [ - + ]: 3 : if(bPDFExport)
886 : : {
887 : : // PDF export. Emulate data handling from UnoControlPDFExportContact
888 : : // I have now moved describePDFControl to toolkit, thus i can implement the PDF
889 : : // form control support now as follows
890 : 0 : ::std::auto_ptr< ::vcl::PDFWriter::AnyWidget > pPDFControl;
891 [ # # ]: 0 : ::toolkitform::describePDFControl( rXControl, pPDFControl, *mpPDFExtOutDevData );
892 : :
893 [ # # ]: 0 : if(pPDFControl.get())
894 : : {
895 : : // still need to fill in the location (is a class Rectangle)
896 [ # # ]: 0 : const basegfx::B2DRange aRangeLogic(rControlPrimitive.getB2DRange(getViewInformation2D()));
897 : : const Rectangle aRectLogic(
898 [ # # ][ # # ]: 0 : (sal_Int32)floor(aRangeLogic.getMinX()), (sal_Int32)floor(aRangeLogic.getMinY()),
899 [ # # ][ # # ]: 0 : (sal_Int32)ceil(aRangeLogic.getMaxX()), (sal_Int32)ceil(aRangeLogic.getMaxY()));
[ # # ]
900 : 0 : pPDFControl->Location = aRectLogic;
901 : :
902 [ # # ]: 0 : Size aFontSize(pPDFControl->TextFont.GetSize());
903 [ # # ][ # # ]: 0 : aFontSize = mpOutputDevice->LogicToLogic(aFontSize, MapMode(MAP_POINT), mpOutputDevice->GetMapMode());
[ # # ]
904 [ # # ]: 0 : pPDFControl->TextFont.SetSize(aFontSize);
905 : :
906 [ # # ]: 0 : mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Form);
907 [ # # ]: 0 : mpPDFExtOutDevData->CreateControl(*pPDFControl.get());
908 [ # # ]: 0 : mpPDFExtOutDevData->EndStructureElement();
909 : :
910 : : // no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject);
911 : : // do not process recursively
912 : 0 : bDoProcessRecursively = false;
913 : : }
914 : : else
915 : : {
916 : : // PDF export did not work, try simple output.
917 : : // Fallback to printer output by not setting bDoProcessRecursively
918 : : // to false.
919 [ # # ]: 0 : }
920 : : }
921 : :
922 : : // #i93169# used flag the wrong way; true means that nothing was done yet
923 [ + - ]: 3 : if(bDoProcessRecursively)
924 : : {
925 : : // printer output
926 : : try
927 : : {
928 : : // remember old graphics and create new
929 [ + - ]: 3 : uno::Reference< awt::XView > xControlView(rXControl, uno::UNO_QUERY_THROW);
930 [ + - ][ + - ]: 3 : const uno::Reference< awt::XGraphics > xOriginalGraphics(xControlView->getGraphics());
931 [ + - ]: 3 : const uno::Reference< awt::XGraphics > xNewGraphics(mpOutputDevice->CreateUnoGraphics());
932 : :
933 [ + - ]: 3 : if(xNewGraphics.is())
934 : : {
935 : : // link graphics and view
936 [ + - ][ + - ]: 3 : xControlView->setGraphics(xNewGraphics);
937 : :
938 : : // get position
939 [ + - ][ + - ]: 3 : const basegfx::B2DHomMatrix aObjectToDiscrete(getViewInformation2D().getObjectToViewTransformation() * rControlPrimitive.getTransform());
940 [ + - ]: 3 : const basegfx::B2DPoint aTopLeftDiscrete(aObjectToDiscrete * basegfx::B2DPoint(0.0, 0.0));
941 : :
942 : : // draw it
943 [ + - ][ + - ]: 3 : xControlView->draw(basegfx::fround(aTopLeftDiscrete.getX()), basegfx::fround(aTopLeftDiscrete.getY()));
944 : 3 : bDoProcessRecursively = false;
945 : :
946 : : // restore original graphics
947 [ + - ][ + - ]: 3 : xControlView->setGraphics(xOriginalGraphics);
[ + - ]
948 [ # # ]: 3 : }
949 : : }
950 [ # # ]: 0 : catch( const uno::Exception& )
951 : : {
952 : : OSL_FAIL("VclMetafileProcessor2D: Printing of Control failed, caught an exception!");
953 : : }
954 : : }
955 : :
956 : : // process recursively if not done yet to export as decomposition (bitmap)
957 [ - + ]: 3 : if(bDoProcessRecursively)
958 : : {
959 [ # # ][ # # ]: 3 : process(rControlPrimitive.get2DDecomposition(getViewInformation2D()));
[ # # ]
960 : : }
961 : : }
962 : :
963 : : break;
964 : : }
965 : : case PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D :
966 : : {
967 : : // support for FIELD_SEQ_BEGIN, FIELD_SEQ_END and URL. It wraps text primitives (but is not limited to)
968 : : // thus do the MetafileAction embedding stuff but just handle recursively.
969 : 8 : const primitive2d::TextHierarchyFieldPrimitive2D& rFieldPrimitive = static_cast< const primitive2d::TextHierarchyFieldPrimitive2D& >(rCandidate);
970 : 8 : const rtl::OString aCommentStringCommon(RTL_CONSTASCII_STRINGPARAM("FIELD_SEQ_BEGIN"));
971 : 8 : const rtl::OString aCommentStringPage(RTL_CONSTASCII_STRINGPARAM("FIELD_SEQ_BEGIN;PageField"));
972 : 8 : const rtl::OString aCommentStringEnd(RTL_CONSTASCII_STRINGPARAM("FIELD_SEQ_END"));
973 : :
974 [ + - - ]: 8 : switch(rFieldPrimitive.getType())
975 : : {
976 : : default : // case drawinglayer::primitive2d::FIELD_TYPE_COMMON :
977 : : {
978 [ + - ][ + - ]: 8 : mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon));
[ + - ]
979 : 8 : break;
980 : : }
981 : : case drawinglayer::primitive2d::FIELD_TYPE_PAGE :
982 : : {
983 [ # # ][ # # ]: 0 : mpMetaFile->AddAction(new MetaCommentAction(aCommentStringPage));
[ # # ]
984 : 0 : break;
985 : : }
986 : : case drawinglayer::primitive2d::FIELD_TYPE_URL :
987 : : {
988 : 0 : const rtl::OUString& rURL = rFieldPrimitive.getString();
989 [ # # ]: 0 : const String aOldString(rURL);
990 [ # # ][ # # ]: 0 : mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast< const sal_uInt8* >(aOldString.GetBuffer()), 2 * aOldString.Len()));
[ # # ]
991 [ # # ]: 0 : break;
992 : : }
993 : : }
994 : :
995 : : // process recursively
996 [ + - ]: 8 : const primitive2d::Primitive2DSequence rContent = rFieldPrimitive.get2DDecomposition(getViewInformation2D());
997 [ + - ]: 8 : process(rContent);
998 : :
999 : : // for the end comment the type is not relevant yet, they are all the same. Just add.
1000 [ + - ][ + - ]: 8 : mpMetaFile->AddAction(new MetaCommentAction(aCommentStringEnd));
[ + - ]
1001 : :
1002 [ - + ][ # # ]: 8 : if(mpPDFExtOutDevData && drawinglayer::primitive2d::FIELD_TYPE_URL == rFieldPrimitive.getType())
[ - + ]
1003 : : {
1004 : : // emulate data handling from ImpEditEngine::Paint
1005 [ # # ]: 0 : const basegfx::B2DRange aViewRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
1006 : : const Rectangle aRectLogic(
1007 [ # # ][ # # ]: 0 : (sal_Int32)floor(aViewRange.getMinX()), (sal_Int32)floor(aViewRange.getMinY()),
1008 [ # # ][ # # ]: 0 : (sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY()));
[ # # ]
1009 : 0 : vcl::PDFExtOutDevBookmarkEntry aBookmark;
1010 [ # # ]: 0 : aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic);
1011 : 0 : aBookmark.aBookmark = rFieldPrimitive.getString();
1012 [ # # ]: 0 : std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = mpPDFExtOutDevData->GetBookmarks();
1013 [ # # ]: 0 : rBookmarks.push_back( aBookmark );
1014 : : }
1015 : :
1016 [ + - ]: 8 : break;
1017 : : }
1018 : : case PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D :
1019 : : {
1020 : 3844 : const primitive2d::TextHierarchyLinePrimitive2D& rLinePrimitive = static_cast< const primitive2d::TextHierarchyLinePrimitive2D& >(rCandidate);
1021 : 3844 : const rtl::OString aCommentString(RTL_CONSTASCII_STRINGPARAM("XTEXT_EOL"));
1022 : :
1023 : : // process recursively and add MetaFile comment
1024 [ + - ][ + - ]: 3844 : process(rLinePrimitive.get2DDecomposition(getViewInformation2D()));
[ + - ]
1025 [ + - ][ + - ]: 3844 : mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
[ + - ]
1026 : :
1027 : 3844 : break;
1028 : : }
1029 : : case PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D :
1030 : : {
1031 : : // in Outliner::PaintBullet(), a MetafileComment for bullets is added, too. The
1032 : : // "XTEXT_EOC" is used, use here, too.
1033 : 0 : const primitive2d::TextHierarchyBulletPrimitive2D& rBulletPrimitive = static_cast< const primitive2d::TextHierarchyBulletPrimitive2D& >(rCandidate);
1034 : 0 : const rtl::OString aCommentString(RTL_CONSTASCII_STRINGPARAM("XTEXT_EOC"));
1035 : :
1036 : : // process recursively and add MetaFile comment
1037 [ # # ][ # # ]: 0 : process(rBulletPrimitive.get2DDecomposition(getViewInformation2D()));
[ # # ]
1038 [ # # ][ # # ]: 0 : mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
[ # # ]
1039 : :
1040 : 0 : break;
1041 : : }
1042 : : case PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D :
1043 : : {
1044 : 3844 : const primitive2d::TextHierarchyParagraphPrimitive2D& rParagraphPrimitive = static_cast< const primitive2d::TextHierarchyParagraphPrimitive2D& >(rCandidate);
1045 : 3844 : const rtl::OString aCommentString(RTL_CONSTASCII_STRINGPARAM("XTEXT_EOP"));
1046 : :
1047 [ - + ]: 3844 : if(mpPDFExtOutDevData)
1048 : : {
1049 : : // emulate data handling from ImpEditEngine::Paint
1050 [ # # ]: 0 : mpPDFExtOutDevData->BeginStructureElement( vcl::PDFWriter::Paragraph );
1051 : : }
1052 : :
1053 : : // process recursively and add MetaFile comment
1054 [ + - ][ + - ]: 3844 : process(rParagraphPrimitive.get2DDecomposition(getViewInformation2D()));
[ + - ]
1055 [ + - ][ + - ]: 3844 : mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
[ + - ]
1056 : :
1057 [ - + ]: 3844 : if(mpPDFExtOutDevData)
1058 : : {
1059 : : // emulate data handling from ImpEditEngine::Paint
1060 [ # # ]: 0 : mpPDFExtOutDevData->EndStructureElement();
1061 : : }
1062 : :
1063 : 3844 : break;
1064 : : }
1065 : : case PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D :
1066 : : {
1067 : 3844 : const primitive2d::TextHierarchyBlockPrimitive2D& rBlockPrimitive = static_cast< const primitive2d::TextHierarchyBlockPrimitive2D& >(rCandidate);
1068 : 3844 : const rtl::OString aCommentStringA(RTL_CONSTASCII_STRINGPARAM("XTEXT_PAINTSHAPE_BEGIN"));
1069 : 3844 : const rtl::OString aCommentStringB(RTL_CONSTASCII_STRINGPARAM("XTEXT_PAINTSHAPE_END"));
1070 : :
1071 : : // add MetaFile comment, process recursively and add MetaFile comment
1072 [ + - ][ + - ]: 3844 : mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA));
[ + - ]
1073 [ + - ][ + - ]: 3844 : process(rBlockPrimitive.get2DDecomposition(getViewInformation2D()));
[ + - ]
1074 [ + - ][ + - ]: 3844 : mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB));
[ + - ]
1075 : :
1076 : 3844 : break;
1077 : : }
1078 : : case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
1079 : : case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D :
1080 : : {
1081 : : // for supporting TEXT_ MetaFile actions there is more to do here; get the candidate
1082 : 3844 : const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate = static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate);
1083 : : // const primitive2d::TextDecoratedPortionPrimitive2D* pTextDecoratedCandidate = dynamic_cast< const primitive2d::TextDecoratedPortionPrimitive2D* >(&rCandidate);
1084 : :
1085 : : // Adapt evtl. used special DrawMode
1086 : 3844 : const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode());
1087 : 3844 : adaptTextToFillDrawMode();
1088 : :
1089 : : // directdraw of text simple portion; use default processing
1090 : 3844 : RenderTextSimpleOrDecoratedPortionPrimitive2D(rTextCandidate);
1091 : :
1092 : : // restore DrawMode
1093 : 3844 : mpOutputDevice->SetDrawMode(nOriginalDrawMode);
1094 : :
1095 : : // #i101169# if(pTextDecoratedCandidate)
1096 : : {
1097 : : // support for TEXT_ MetaFile actions only for decorated texts
1098 [ + + ]: 3844 : if(!mxBreakIterator.is())
1099 : : {
1100 [ + - ]: 11 : uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory());
1101 [ + - ][ + - ]: 11 : mxBreakIterator.set(xMSF->createInstance("com.sun.star.i18n.BreakIterator"), uno::UNO_QUERY);
[ + - ]
1102 : : }
1103 : :
1104 [ + - ]: 3844 : if(mxBreakIterator.is())
1105 : : {
1106 : 3844 : const rtl::OUString& rTxt = rTextCandidate.getText();
1107 : 3844 : const sal_Int32 nTextLength(rTextCandidate.getTextLength()); // rTxt.getLength());
1108 : :
1109 [ + - ]: 3844 : if(nTextLength)
1110 : : {
1111 : 3844 : const ::com::sun::star::lang::Locale& rLocale = rTextCandidate.getLocale();
1112 : 3844 : const sal_Int32 nTextPosition(rTextCandidate.getTextPosition());
1113 : :
1114 : : sal_Int32 nDone;
1115 [ + - ][ + - ]: 3844 : sal_Int32 nNextCellBreak(mxBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone));
1116 [ + - ][ + - ]: 3844 : ::com::sun::star::i18n::Boundary nNextWordBoundary(mxBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True));
1117 [ + - ][ + - ]: 3844 : sal_Int32 nNextSentenceBreak(mxBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale));
1118 : 3844 : const rtl::OString aCommentStringA(RTL_CONSTASCII_STRINGPARAM("XTEXT_EOC"));
1119 : 3844 : const rtl::OString aCommentStringB(RTL_CONSTASCII_STRINGPARAM("XTEXT_EOW"));
1120 : 3844 : const rtl::OString aCommentStringC(RTL_CONSTASCII_STRINGPARAM("XTEXT_EOS"));
1121 : :
1122 [ + + ]: 35195 : for(sal_Int32 i(nTextPosition); i < nTextPosition + nTextLength; i++)
1123 : : {
1124 : : // create the entries for the respective break positions
1125 [ + - ]: 31351 : if(i == nNextCellBreak)
1126 : : {
1127 [ + - ][ + - ]: 31351 : mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA, i - nTextPosition));
[ + - ]
1128 [ + - ][ + - ]: 31351 : nNextCellBreak = mxBreakIterator->nextCharacters(rTxt, i, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
1129 : : }
1130 [ + + ]: 31351 : if(i == nNextWordBoundary.endPos)
1131 : : {
1132 [ + - ][ + - ]: 2748 : mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB, i - nTextPosition));
[ + - ]
1133 [ + - ][ + - ]: 2748 : nNextWordBoundary = mxBreakIterator->getWordBoundary(rTxt, i + 1, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True);
1134 : : }
1135 [ + + ]: 31351 : if(i == nNextSentenceBreak)
1136 : : {
1137 [ + - ][ + - ]: 12 : mpMetaFile->AddAction(new MetaCommentAction(aCommentStringC, i - nTextPosition));
[ + - ]
1138 [ + - ][ + - ]: 12 : nNextSentenceBreak = mxBreakIterator->endOfSentence(rTxt, i + 1, rLocale);
1139 : : }
1140 : 3844 : }
1141 : 3844 : }
1142 : : }
1143 : : }
1144 : :
1145 : 3844 : break;
1146 : : }
1147 : : case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
1148 : : {
1149 : 6508 : const primitive2d::PolygonHairlinePrimitive2D& rHairlinePrimitive = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate);
1150 : 6508 : const basegfx::B2DPolygon& rBasePolygon = rHairlinePrimitive.getB2DPolygon();
1151 : :
1152 [ - + ]: 6508 : if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
1153 : : {
1154 : : // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1155 : : // per polygon. If there are more, split the polygon in half and call recursively
1156 [ # # ][ # # ]: 0 : basegfx::B2DPolygon aLeft, aRight;
1157 [ # # ]: 0 : splitLinePolygon(rBasePolygon, aLeft, aRight);
1158 [ # # ]: 0 : const primitive2d::PolygonHairlinePrimitive2D aPLeft(aLeft, rHairlinePrimitive.getBColor());
1159 [ # # ]: 0 : const primitive2d::PolygonHairlinePrimitive2D aPRight(aRight, rHairlinePrimitive.getBColor());
1160 : :
1161 [ # # ]: 0 : processBasePrimitive2D(aPLeft);
1162 [ # # ][ # # ]: 0 : processBasePrimitive2D(aPRight);
[ # # ][ # # ]
[ # # ]
1163 : : }
1164 : : else
1165 : : {
1166 : : // direct draw of hairline; use default processing
1167 : : // support SvtGraphicStroke MetaCommentAction
1168 [ + - ]: 6508 : const basegfx::BColor aLineColor(maBColorModifierStack.getModifiedColor(rHairlinePrimitive.getBColor()));
1169 : : SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
1170 : 6508 : rHairlinePrimitive.getB2DPolygon(),
1171 : : &aLineColor,
1172 [ + - ]: 6508 : 0, 0, 0, 0);
1173 : :
1174 [ + - ]: 6508 : impStartSvtGraphicStroke(pSvtGraphicStroke);
1175 [ + - ]: 6508 : RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate), false);
1176 [ + - ]: 6508 : impEndSvtGraphicStroke(pSvtGraphicStroke);
1177 : : }
1178 : 6508 : break;
1179 : : }
1180 : : case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D :
1181 : : {
1182 : 4735 : const primitive2d::PolygonStrokePrimitive2D& rStrokePrimitive = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate);
1183 : 4735 : const basegfx::B2DPolygon& rBasePolygon = rStrokePrimitive.getB2DPolygon();
1184 : :
1185 [ - + ]: 4735 : if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
1186 : : {
1187 : : // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1188 : : // per polygon. If there are more, split the polygon in half and call recursively
1189 [ # # ][ # # ]: 0 : basegfx::B2DPolygon aLeft, aRight;
1190 [ # # ]: 0 : splitLinePolygon(rBasePolygon, aLeft, aRight);
1191 : : const primitive2d::PolygonStrokePrimitive2D aPLeft(
1192 [ # # ]: 0 : aLeft, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute());
1193 : : const primitive2d::PolygonStrokePrimitive2D aPRight(
1194 [ # # ]: 0 : aRight, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute());
1195 : :
1196 [ # # ]: 0 : processBasePrimitive2D(aPLeft);
1197 [ # # ][ # # ]: 0 : processBasePrimitive2D(aPRight);
[ # # ][ # # ]
[ # # ]
1198 : : }
1199 : : else
1200 : : {
1201 : : // support SvtGraphicStroke MetaCommentAction
1202 : : SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
1203 : : rBasePolygon, 0,
1204 : 4735 : &rStrokePrimitive.getLineAttribute(),
1205 : 4735 : &rStrokePrimitive.getStrokeAttribute(),
1206 : 4735 : 0, 0);
1207 : :
1208 : 4735 : impStartSvtGraphicStroke(pSvtGraphicStroke);
1209 : 4735 : const attribute::LineAttribute& rLine = rStrokePrimitive.getLineAttribute();
1210 : :
1211 : : // create MetaPolyLineActions, but without LINE_DASH
1212 [ + + ][ + - ]: 4735 : if(basegfx::fTools::more(rLine.getWidth(), 0.0))
1213 : : {
1214 : 403 : const attribute::StrokeAttribute& rStroke = rStrokePrimitive.getStrokeAttribute();
1215 [ + - ]: 403 : basegfx::B2DPolyPolygon aHairLinePolyPolygon;
1216 : :
1217 [ + - ][ + - ]: 403 : if(0.0 == rStroke.getFullDotDashLen())
1218 : : {
1219 [ + - ]: 403 : aHairLinePolyPolygon.append(rBasePolygon);
1220 : : }
1221 : : else
1222 : : {
1223 : : basegfx::tools::applyLineDashing(
1224 [ # # ]: 0 : rBasePolygon, rStroke.getDotDashArray(),
1225 [ # # ][ # # ]: 0 : &aHairLinePolyPolygon, 0, rStroke.getFullDotDashLen());
1226 : : }
1227 : :
1228 [ + - ][ + - ]: 403 : const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLine.getColor()));
1229 [ + - ]: 403 : mpOutputDevice->SetLineColor(Color(aHairlineColor));
1230 [ + - ]: 403 : mpOutputDevice->SetFillColor();
1231 [ + - ]: 403 : aHairLinePolyPolygon.transform(maCurrentTransformation);
1232 : :
1233 : : // #i113922# LineWidth needs to be transformed, too
1234 [ + - ][ + - ]: 403 : const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation * basegfx::B2DVector(rLine.getWidth(), 0.0));
1235 [ + - ]: 403 : const double fDiscreteLineWidth(aDiscreteUnit.getLength());
1236 : :
1237 [ + - ]: 403 : LineInfo aLineInfo(LINE_SOLID, basegfx::fround(fDiscreteLineWidth));
1238 [ + - ][ + - ]: 403 : aLineInfo.SetLineJoin(rLine.getLineJoin());
1239 : :
1240 [ + - ][ + + ]: 806 : for(sal_uInt32 a(0); a < aHairLinePolyPolygon.count(); a++)
1241 : : {
1242 [ + - ]: 403 : const basegfx::B2DPolygon aCandidate(aHairLinePolyPolygon.getB2DPolygon(a));
1243 : :
1244 [ + - ][ + - ]: 403 : if(aCandidate.count() > 1)
1245 : : {
1246 [ + - ]: 403 : const Polygon aToolsPolygon(aCandidate);
1247 : :
1248 [ + - ][ + - ]: 403 : mpMetaFile->AddAction(new MetaPolyLineAction(aToolsPolygon, aLineInfo));
[ + - ][ + - ]
1249 : : }
1250 [ + - ][ + - ]: 806 : }
[ + - ]
1251 : : }
1252 : : else
1253 : : {
1254 [ + - ]: 4332 : process(rCandidate.get2DDecomposition(getViewInformation2D()));
1255 : : }
1256 : :
1257 : 4735 : impEndSvtGraphicStroke(pSvtGraphicStroke);
1258 : : }
1259 : :
1260 : 4735 : break;
1261 : : }
1262 : : case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D :
1263 : : {
1264 : 3 : const primitive2d::PolygonStrokeArrowPrimitive2D& rStrokeArrowPrimitive = static_cast< const primitive2d::PolygonStrokeArrowPrimitive2D& >(rCandidate);
1265 : 3 : const basegfx::B2DPolygon& rBasePolygon = rStrokeArrowPrimitive.getB2DPolygon();
1266 : :
1267 [ - + ]: 3 : if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
1268 : : {
1269 : : // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1270 : : // per polygon. If there are more, split the polygon in half and call recursively
1271 [ # # ][ # # ]: 0 : basegfx::B2DPolygon aLeft, aRight;
1272 [ # # ]: 0 : splitLinePolygon(rBasePolygon, aLeft, aRight);
1273 [ # # ]: 0 : const attribute::LineStartEndAttribute aEmpty;
1274 : : const primitive2d::PolygonStrokeArrowPrimitive2D aPLeft(
1275 : : aLeft,
1276 : 0 : rStrokeArrowPrimitive.getLineAttribute(),
1277 : 0 : rStrokeArrowPrimitive.getStrokeAttribute(),
1278 : 0 : rStrokeArrowPrimitive.getStart(),
1279 [ # # ]: 0 : aEmpty);
1280 : : const primitive2d::PolygonStrokeArrowPrimitive2D aPRight(
1281 : : aRight,
1282 : 0 : rStrokeArrowPrimitive.getLineAttribute(),
1283 : 0 : rStrokeArrowPrimitive.getStrokeAttribute(),
1284 : : aEmpty,
1285 [ # # ]: 0 : rStrokeArrowPrimitive.getEnd());
1286 : :
1287 [ # # ]: 0 : processBasePrimitive2D(aPLeft);
1288 [ # # ][ # # ]: 0 : processBasePrimitive2D(aPRight);
[ # # ][ # # ]
[ # # ][ # # ]
1289 : : }
1290 : : else
1291 : : {
1292 : : // support SvtGraphicStroke MetaCommentAction
1293 : : SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
1294 : : rBasePolygon, 0,
1295 : 3 : &rStrokeArrowPrimitive.getLineAttribute(),
1296 : 3 : &rStrokeArrowPrimitive.getStrokeAttribute(),
1297 : 3 : &rStrokeArrowPrimitive.getStart(),
1298 : 6 : &rStrokeArrowPrimitive.getEnd());
1299 : :
1300 : 3 : impStartSvtGraphicStroke(pSvtGraphicStroke);
1301 [ + - ]: 3 : process(rCandidate.get2DDecomposition(getViewInformation2D()));
1302 : 3 : impEndSvtGraphicStroke(pSvtGraphicStroke);
1303 : : }
1304 : :
1305 : 3 : break;
1306 : : }
1307 : : case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
1308 : : {
1309 : : // direct draw of transformed BitmapEx primitive; use default processing
1310 : 25 : RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
1311 : 25 : break;
1312 : : }
1313 : : case PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D :
1314 : : {
1315 : : // direct draw of transformed RenderGraphic primitive; use default processing
1316 : 0 : RenderRenderGraphicPrimitive2D(static_cast< const primitive2d::RenderGraphicPrimitive2D& >(rCandidate));
1317 : 0 : break;
1318 : : }
1319 : : case PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D :
1320 : : {
1321 : : // need to handle PolyPolygonBitmapPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
1322 : 0 : const primitive2d::PolyPolygonBitmapPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonBitmapPrimitive2D& >(rCandidate);
1323 [ # # ]: 0 : basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon());
1324 : :
1325 [ # # ][ # # ]: 0 : if(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1326 : : {
1327 : : // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1328 : : // per polygon. If there are more use the splitted polygon and call recursively
1329 : : const primitive2d::PolyPolygonBitmapPrimitive2D aSplitted(
1330 : : aLocalPolyPolygon,
1331 [ # # ]: 0 : rBitmapCandidate.getFillBitmap());
1332 : :
1333 [ # # ][ # # ]: 0 : processBasePrimitive2D(aSplitted);
1334 : : }
1335 : : else
1336 : : {
1337 : 0 : SvtGraphicFill* pSvtGraphicFill = 0;
1338 : :
1339 [ # # ][ # # ]: 0 : if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
[ # # ][ # # ]
1340 : : {
1341 [ # # ]: 0 : aLocalPolyPolygon.transform(maCurrentTransformation);
1342 : : // calculate transformation. Get real object size, all values in FillBitmapAttribute
1343 : : // are relative to the unified object
1344 : 0 : const attribute::FillBitmapAttribute& rFillBitmapAttribute = rBitmapCandidate .getFillBitmap();
1345 [ # # ]: 0 : const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(aLocalPolyPolygon));
1346 [ # # ]: 0 : const basegfx::B2DVector aOutlineSize(aOutlineRange.getRange());
1347 : :
1348 : : // get absolute values
1349 [ # # ]: 0 : const basegfx::B2DVector aFillBitmapSize(rFillBitmapAttribute.getSize() * aOutlineSize);
1350 [ # # ]: 0 : const basegfx::B2DPoint aFillBitmapTopLeft(rFillBitmapAttribute.getTopLeft() * aOutlineSize);
1351 : :
1352 : : // the scaling needs scale from pixel to logic coordinate system
1353 [ # # ]: 0 : const BitmapEx& rBitmapEx = rFillBitmapAttribute.getBitmapEx();
1354 : 0 : Size aBmpSizePixel(rBitmapEx.GetSizePixel());
1355 : :
1356 [ # # ]: 0 : if(!aBmpSizePixel.Width())
1357 : : {
1358 : 0 : aBmpSizePixel.Width() = 1;
1359 : : }
1360 : :
1361 [ # # ]: 0 : if(!aBmpSizePixel.Height())
1362 : : {
1363 : 0 : aBmpSizePixel.Height() = 1;
1364 : : }
1365 : :
1366 : : // setup transformation like in impgrfll
1367 [ # # ]: 0 : SvtGraphicFill::Transform aTransform;
1368 : :
1369 : : // scale values are divided by bitmap pixel sizes
1370 : 0 : aTransform.matrix[0] = aFillBitmapSize.getX() / aBmpSizePixel.Width();
1371 : 0 : aTransform.matrix[4] = aFillBitmapSize.getY() / aBmpSizePixel.Height();
1372 : :
1373 : : // translates are absolute
1374 : 0 : aTransform.matrix[2] = aFillBitmapTopLeft.getX();
1375 : 0 : aTransform.matrix[5] = aFillBitmapTopLeft.getY();
1376 : :
1377 : : // setup fill graphic like in impgrfll
1378 [ # # ]: 0 : Graphic aFillGraphic = Graphic(rBitmapEx);
1379 [ # # ][ # # ]: 0 : aFillGraphic.SetPrefMapMode(MapMode(MAP_PIXEL));
[ # # ]
1380 [ # # ]: 0 : aFillGraphic.SetPrefSize(aBmpSizePixel);
1381 : :
1382 : : pSvtGraphicFill = new SvtGraphicFill(
1383 : : getFillPolyPolygon(aLocalPolyPolygon),
1384 : : Color(),
1385 : : 0.0,
1386 : : SvtGraphicFill::fillEvenOdd,
1387 : : SvtGraphicFill::fillTexture,
1388 : : aTransform,
1389 [ # # ]: 0 : rFillBitmapAttribute.getTiling(),
1390 : : SvtGraphicFill::hatchSingle,
1391 : : Color(),
1392 : : SvtGraphicFill::gradientLinear,
1393 : : Color(),
1394 : : Color(),
1395 : : 0,
1396 [ # # ][ # # ]: 0 : aFillGraphic);
[ # # ][ # # ]
[ # # ]
1397 : : }
1398 : :
1399 : : // Do use decomposition; encapsulate with SvtGraphicFill
1400 [ # # ]: 0 : impStartSvtGraphicFill(pSvtGraphicFill);
1401 [ # # ][ # # ]: 0 : process(rCandidate.get2DDecomposition(getViewInformation2D()));
[ # # ]
1402 [ # # ]: 0 : impEndSvtGraphicFill(pSvtGraphicFill);
1403 : : }
1404 : :
1405 [ # # ]: 0 : break;
1406 : : }
1407 : : case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D :
1408 : : {
1409 : : // need to handle PolyPolygonHatchPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
1410 : 0 : const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate);
1411 : 0 : const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch();
1412 [ # # ]: 0 : basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon());
1413 : :
1414 : : // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1415 : : // per polygon. Split polygon until there are less than that
1416 [ # # ][ # # ]: 0 : while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1417 : : ;
1418 : :
1419 [ # # ][ # # ]: 0 : if(rFillHatchAttribute.isFillBackground())
1420 : : {
1421 : : // with fixing #i111954# (see below) the possible background
1422 : : // fill of a hatched object was lost.Generate a background fill
1423 : : // primitive and render it
1424 : : const primitive2d::Primitive2DReference xBackground(
1425 : : new primitive2d::PolyPolygonColorPrimitive2D(
1426 : : aLocalPolyPolygon,
1427 [ # # ][ # # ]: 0 : rHatchCandidate.getBackgroundColor()));
[ # # ]
1428 : :
1429 [ # # ][ # # ]: 0 : process(primitive2d::Primitive2DSequence(&xBackground, 1));
[ # # ]
1430 : : }
1431 : :
1432 : 0 : SvtGraphicFill* pSvtGraphicFill = 0;
1433 [ # # ]: 0 : aLocalPolyPolygon.transform(maCurrentTransformation);
1434 : :
1435 [ # # ][ # # ]: 0 : if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
[ # # ][ # # ]
1436 : : {
1437 : : // re-create a VCL hatch as base data
1438 : 0 : SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle);
1439 : :
1440 [ # # ]: 0 : switch(rFillHatchAttribute.getStyle())
[ # # # ]
1441 : : {
1442 : : default: // attribute::HATCHSTYLE_SINGLE :
1443 : : {
1444 : 0 : eHatch = SvtGraphicFill::hatchSingle;
1445 : 0 : break;
1446 : : }
1447 : : case attribute::HATCHSTYLE_DOUBLE :
1448 : : {
1449 : 0 : eHatch = SvtGraphicFill::hatchDouble;
1450 : 0 : break;
1451 : : }
1452 : : case attribute::HATCHSTYLE_TRIPLE :
1453 : : {
1454 : 0 : eHatch = SvtGraphicFill::hatchTriple;
1455 : 0 : break;
1456 : : }
1457 : : }
1458 : :
1459 [ # # ]: 0 : SvtGraphicFill::Transform aTransform;
1460 : :
1461 : : // scale
1462 [ # # ]: 0 : aTransform.matrix[0] *= rFillHatchAttribute.getDistance();
1463 [ # # ]: 0 : aTransform.matrix[4] *= rFillHatchAttribute.getDistance();
1464 : :
1465 : : // rotate (was never correct in impgrfll anyways, use correct angle now)
1466 [ # # ]: 0 : aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle());
1467 [ # # ]: 0 : aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle());
1468 [ # # ]: 0 : aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle());
1469 [ # # ]: 0 : aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle());
1470 : :
1471 : : pSvtGraphicFill = new SvtGraphicFill(
1472 : : getFillPolyPolygon(aLocalPolyPolygon),
1473 : : Color(),
1474 : : 0.0,
1475 : : SvtGraphicFill::fillEvenOdd,
1476 : : SvtGraphicFill::fillHatch,
1477 : : aTransform,
1478 : : false,
1479 : : eHatch,
1480 [ # # ]: 0 : Color(rFillHatchAttribute.getColor()),
1481 : : SvtGraphicFill::gradientLinear,
1482 : : Color(),
1483 : : Color(),
1484 : : 0,
1485 [ # # ][ # # ]: 0 : Graphic());
[ # # ][ # # ]
[ # # ][ # # ]
1486 : : }
1487 : :
1488 : : // Do use decomposition; encapsulate with SvtGraphicFill
1489 [ # # ]: 0 : impStartSvtGraphicFill(pSvtGraphicFill);
1490 : :
1491 : : // #i111954# do NOT use decomposition, but use direct VCL-command
1492 : : // process(rCandidate.get2DDecomposition(getViewInformation2D()));
1493 [ # # ]: 0 : const PolyPolygon aToolsPolyPolygon(aLocalPolyPolygon);
1494 : : const HatchStyle aHatchStyle(
1495 [ # # ]: 0 : attribute::HATCHSTYLE_SINGLE == rFillHatchAttribute.getStyle() ? HATCH_SINGLE :
1496 [ # # ]: 0 : attribute::HATCHSTYLE_DOUBLE == rFillHatchAttribute.getStyle() ? HATCH_DOUBLE :
1497 [ # # ][ # # ]: 0 : HATCH_TRIPLE);
1498 : :
1499 : : mpOutputDevice->DrawHatch(aToolsPolyPolygon,
1500 : : Hatch(aHatchStyle,
1501 [ # # ]: 0 : Color(rFillHatchAttribute.getColor()),
1502 : : basegfx::fround(rFillHatchAttribute.getDistance()),
1503 [ # # ][ # # ]: 0 : basegfx::fround(rFillHatchAttribute.getAngle() / F_PI1800)));
[ # # ][ # # ]
[ # # ]
1504 : :
1505 [ # # ]: 0 : impEndSvtGraphicFill(pSvtGraphicFill);
1506 : :
1507 [ # # ][ # # ]: 0 : break;
1508 : : }
1509 : : case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
1510 : : {
1511 : 0 : const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate);
1512 [ # # ]: 0 : basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon());
1513 : :
1514 : : // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1515 : : // per polygon. Split polygon until there are less than that
1516 [ # # ][ # # ]: 0 : while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1517 : : ;
1518 : :
1519 : : // for support of MetaCommentActions of the form XGRAD_SEQ_BEGIN, XGRAD_SEQ_END
1520 : : // it is safest to use the VCL OutputDevice::DrawGradient method which creates those.
1521 : : // re-create a VCL-gradient from FillGradientPrimitive2D and the needed tools PolyPolygon
1522 [ # # ]: 0 : Gradient aVCLGradient;
1523 [ # # ]: 0 : impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rGradientCandidate.getFillGradient(), false);
1524 [ # # ]: 0 : aLocalPolyPolygon.transform(maCurrentTransformation);
1525 : :
1526 : : // #i82145# ATM VCL printing of gradients using curved shapes does not work,
1527 : : // i submitted the bug with the given ID to THB. When that task is fixed it is
1528 : : // necessary to again remove this subdivision since it decreases possible
1529 : : // printing quality (not even resolution-dependent for now). THB will tell
1530 : : // me when that task is fixed in the master
1531 : : const PolyPolygon aToolsPolyPolygon(
1532 : : getFillPolyPolygon(
1533 [ # # ][ # # ]: 0 : basegfx::tools::adaptiveSubdivideByAngle(aLocalPolyPolygon)));
[ # # ]
1534 : :
1535 : : // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
1536 : 0 : SvtGraphicFill* pSvtGraphicFill = 0;
1537 : :
1538 [ # # ][ # # ]: 0 : if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
[ # # ][ # # ]
1539 : : {
1540 : : // setup gradient stuff like in like in impgrfll
1541 : 0 : SvtGraphicFill::GradientType eGrad(SvtGraphicFill::gradientLinear);
1542 : :
1543 [ # # # ]: 0 : switch(aVCLGradient.GetStyle())
1544 : : {
1545 : : default : // GradientStyle_LINEAR:
1546 : : case GradientStyle_AXIAL:
1547 : 0 : eGrad = SvtGraphicFill::gradientLinear;
1548 : 0 : break;
1549 : : case GradientStyle_RADIAL:
1550 : : case GradientStyle_ELLIPTICAL:
1551 : 0 : eGrad = SvtGraphicFill::gradientRadial;
1552 : 0 : break;
1553 : : case GradientStyle_SQUARE:
1554 : : case GradientStyle_RECT:
1555 : 0 : eGrad = SvtGraphicFill::gradientRectangular;
1556 : 0 : break;
1557 : : }
1558 : :
1559 : : pSvtGraphicFill = new SvtGraphicFill(
1560 : : aToolsPolyPolygon,
1561 : : Color(),
1562 : : 0.0,
1563 : : SvtGraphicFill::fillEvenOdd,
1564 : : SvtGraphicFill::fillGradient,
1565 : : SvtGraphicFill::Transform(),
1566 : : false,
1567 : : SvtGraphicFill::hatchSingle,
1568 : : Color(),
1569 : : eGrad,
1570 : 0 : aVCLGradient.GetStartColor(),
1571 : 0 : aVCLGradient.GetEndColor(),
1572 : 0 : aVCLGradient.GetSteps(),
1573 [ # # ][ # # ]: 0 : Graphic());
[ # # ][ # # ]
[ # # ]
1574 : : }
1575 : :
1576 : : // call VCL directly; encapsulate with SvtGraphicFill
1577 [ # # ]: 0 : impStartSvtGraphicFill(pSvtGraphicFill);
1578 [ # # ]: 0 : mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient);
1579 [ # # ]: 0 : impEndSvtGraphicFill(pSvtGraphicFill);
1580 : :
1581 : : // NO usage of common own gradient randerer, not used ATM for VCL MetaFile, see text above
1582 : : // RenderPolyPolygonGradientPrimitive2D(static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate));
1583 : :
1584 [ # # ][ # # ]: 0 : break;
[ # # ]
1585 : : }
1586 : : case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
1587 : : {
1588 : 1195 : const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
1589 [ + - ]: 1195 : basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
1590 : :
1591 : : // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1592 : : // per polygon. Split polygon until there are less than that
1593 [ + - ][ - + ]: 1195 : while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1594 : : ;
1595 : :
1596 [ + - ]: 1195 : const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
1597 [ + - ]: 1195 : aLocalPolyPolygon.transform(maCurrentTransformation);
1598 : :
1599 : : // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
1600 : 1195 : SvtGraphicFill* pSvtGraphicFill = 0;
1601 : :
1602 [ + - ][ + - ]: 1195 : if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
[ + - ][ + - ]
1603 : : {
1604 : : // setup simple color fill stuff like in impgrfll
1605 : : pSvtGraphicFill = new SvtGraphicFill(
1606 : : getFillPolyPolygon(aLocalPolyPolygon),
1607 : : Color(aPolygonColor),
1608 : : 0.0,
1609 : : SvtGraphicFill::fillEvenOdd,
1610 : : SvtGraphicFill::fillSolid,
1611 : : SvtGraphicFill::Transform(),
1612 : : false,
1613 : : SvtGraphicFill::hatchSingle,
1614 : : Color(),
1615 : : SvtGraphicFill::gradientLinear,
1616 : : Color(),
1617 : : Color(),
1618 : : 0,
1619 [ + - ][ + - ]: 1195 : Graphic());
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1620 : : }
1621 : :
1622 : : // set line and fill color
1623 [ + - ]: 1195 : mpOutputDevice->SetFillColor(Color(aPolygonColor));
1624 [ + - ]: 1195 : mpOutputDevice->SetLineColor();
1625 : :
1626 : : // call VCL directly; encapsulate with SvtGraphicFill
1627 [ + - ]: 1195 : impStartSvtGraphicFill(pSvtGraphicFill);
1628 [ + - ]: 1195 : mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
1629 [ + - ]: 1195 : impEndSvtGraphicFill(pSvtGraphicFill);
1630 : :
1631 [ + - ]: 1195 : break;
1632 : : }
1633 : : case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
1634 : : {
1635 : : // direct draw of MetaFile, use default pocessing
1636 : 0 : RenderMetafilePrimitive2D(static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate));
1637 : 0 : break;
1638 : : }
1639 : : case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
1640 : : {
1641 : : // mask group. Special handling for MetaFiles.
1642 : 0 : const primitive2d::MaskPrimitive2D& rMaskCandidate = static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate);
1643 : :
1644 [ # # ]: 0 : if(rMaskCandidate.getChildren().hasElements())
1645 : : {
1646 [ # # ]: 0 : basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
1647 : :
1648 [ # # ][ # # ]: 0 : if(aMask.count())
1649 : : {
1650 : : // prepare new mask polygon and rescue current one
1651 [ # # ]: 0 : aMask.transform(maCurrentTransformation);
1652 [ # # ]: 0 : const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon);
1653 : :
1654 [ # # ][ # # ]: 0 : if(maClipPolyPolygon.count())
1655 : : {
1656 : : // there is already a clip polygon set; build clipped union of
1657 : : // current mask polygon and new one
1658 : : maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(
1659 : : aMask,
1660 : : maClipPolyPolygon,
1661 : : true, // #i106516# we want the inside of aMask, not the outside
1662 [ # # ][ # # ]: 0 : false);
[ # # ]
1663 : : }
1664 : : else
1665 : : {
1666 : : // use mask directly
1667 [ # # ]: 0 : maClipPolyPolygon = aMask;
1668 : : }
1669 : :
1670 [ # # ][ # # ]: 0 : if(maClipPolyPolygon.count())
1671 : : {
1672 : : // set VCL clip region; subdivide before conversion to tools polygon. Subdivision necessary (!)
1673 : : // Removed subdivision and fixed in Region::ImplPolyPolyRegionToBandRegionFunc() in VCL where
1674 : : // the ClipRegion is built from the Polygon. A AdaptiveSubdivide on the source polygon was missing there
1675 [ # # ]: 0 : mpOutputDevice->Push(PUSH_CLIPREGION);
1676 : : //mpOutputDevice->SetClipRegion(Region(PolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(maClipPolyPolygon))));
1677 [ # # ][ # # ]: 0 : mpOutputDevice->SetClipRegion(Region(PolyPolygon(maClipPolyPolygon)));
[ # # ][ # # ]
[ # # ]
1678 : : }
1679 : :
1680 : : // recursively paint content
1681 [ # # ]: 0 : process(rMaskCandidate.getChildren());
1682 : :
1683 [ # # ][ # # ]: 0 : if(maClipPolyPolygon.count())
1684 : : {
1685 : : // restore VCL clip region
1686 [ # # ]: 0 : mpOutputDevice->Pop();
1687 : : }
1688 : :
1689 : : // restore to rescued clip polygon
1690 [ # # ][ # # ]: 0 : maClipPolyPolygon = aLastClipPolyPolygon;
1691 : : }
1692 : : else
1693 : : {
1694 : : // no mask, no clipping. recursively paint content
1695 [ # # ]: 0 : process(rMaskCandidate.getChildren());
1696 [ # # ]: 0 : }
1697 : : }
1698 : :
1699 : 0 : break;
1700 : : }
1701 : : case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
1702 : : {
1703 : : // modified color group. Force output to unified color. Use default pocessing.
1704 : 0 : RenderModifiedColorPrimitive2D(static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate));
1705 : 0 : break;
1706 : : }
1707 : : case PRIMITIVE2D_ID_HIDDENGEOMETRYPRIMITIVE2D :
1708 : : {
1709 : : // HiddenGeometryPrimitive2D; to rebuilt the old MetaFile creation, it is necessary to
1710 : : // not ignore them (as it was thought), but to add a MetaFile entry for them.
1711 [ + - ]: 5756 : basegfx::B2DRange aInvisibleRange(rCandidate.getB2DRange(getViewInformation2D()));
1712 : :
1713 [ + - ][ + - ]: 5756 : if(!aInvisibleRange.isEmpty())
1714 : : {
1715 [ + - ]: 5756 : aInvisibleRange.transform(maCurrentTransformation);
1716 : : const Rectangle aRectLogic(
1717 [ + - ][ + - ]: 5756 : (sal_Int32)floor(aInvisibleRange.getMinX()), (sal_Int32)floor(aInvisibleRange.getMinY()),
1718 [ + - ][ + - ]: 11512 : (sal_Int32)ceil(aInvisibleRange.getMaxX()), (sal_Int32)ceil(aInvisibleRange.getMaxY()));
[ + - ]
1719 : :
1720 [ + - ]: 5756 : mpOutputDevice->SetFillColor();
1721 [ + - ]: 5756 : mpOutputDevice->SetLineColor();
1722 [ + - ]: 5756 : mpOutputDevice->DrawRect(aRectLogic);
1723 : : }
1724 : :
1725 : : break;
1726 : : }
1727 : : case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D :
1728 : : {
1729 : : // for metafile: Need to examine what the pure vcl version is doing here actually
1730 : : // - uses DrawTransparent with metafile for content and a gradient
1731 : : // - uses DrawTransparent for single PolyPoylgons directly. Can be detected by
1732 : : // checking the content for single PolyPolygonColorPrimitive2D
1733 : 0 : const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate = static_cast< const primitive2d::UnifiedTransparencePrimitive2D& >(rCandidate);
1734 [ # # ]: 0 : const primitive2d::Primitive2DSequence rContent = rUniTransparenceCandidate.getChildren();
1735 : :
1736 [ # # ]: 0 : if(rContent.hasElements())
1737 : : {
1738 [ # # ]: 0 : if(0.0 == rUniTransparenceCandidate.getTransparence())
1739 : : {
1740 : : // not transparent at all, use content
1741 [ # # ]: 0 : process(rUniTransparenceCandidate.getChildren());
1742 : : }
1743 [ # # ][ # # ]: 0 : else if(rUniTransparenceCandidate.getTransparence() > 0.0 && rUniTransparenceCandidate.getTransparence() < 1.0)
[ # # ]
1744 : : {
1745 : : // try to identify a single PolyPolygonColorPrimitive2D in the
1746 : : // content part of the transparence primitive
1747 : 0 : const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = 0;
1748 : : static bool bForceToMetafile(false);
1749 : :
1750 [ # # ][ # # ]: 0 : if(!bForceToMetafile && 1 == rContent.getLength())
[ # # ]
1751 : : {
1752 : 0 : const primitive2d::Primitive2DReference xReference(rContent[0]);
1753 [ # # ][ # # ]: 0 : pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get());
1754 : : }
1755 : :
1756 : : // PolyPolygonGradientPrimitive2D, PolyPolygonHatchPrimitive2D and
1757 : : // PolyPolygonBitmapPrimitive2D are derived from PolyPolygonColorPrimitive2D.
1758 : : // Check also for correct ID to exclude derived implementations
1759 [ # # ][ # # ]: 0 : if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID())
[ # # ][ # # ]
1760 : : {
1761 : : // single transparent PolyPolygon identified, use directly
1762 [ # # ]: 0 : const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
1763 [ # # ]: 0 : basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon());
1764 : :
1765 : : // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1766 : : // per polygon. Split polygon until there are less than that
1767 [ # # ][ # # ]: 0 : while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1768 : : ;
1769 : :
1770 : : // now transform
1771 [ # # ]: 0 : aLocalPolyPolygon.transform(maCurrentTransformation);
1772 : :
1773 : : // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
1774 : 0 : SvtGraphicFill* pSvtGraphicFill = 0;
1775 : :
1776 [ # # ][ # # ]: 0 : if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
[ # # ][ # # ]
1777 : : {
1778 : : // setup simple color with transparence fill stuff like in impgrfll
1779 : : pSvtGraphicFill = new SvtGraphicFill(
1780 : : getFillPolyPolygon(aLocalPolyPolygon),
1781 : : Color(aPolygonColor),
1782 : : rUniTransparenceCandidate.getTransparence(),
1783 : : SvtGraphicFill::fillEvenOdd,
1784 : : SvtGraphicFill::fillSolid,
1785 : : SvtGraphicFill::Transform(),
1786 : : false,
1787 : : SvtGraphicFill::hatchSingle,
1788 : : Color(),
1789 : : SvtGraphicFill::gradientLinear,
1790 : : Color(),
1791 : : Color(),
1792 : : 0,
1793 [ # # ][ # # ]: 0 : Graphic());
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1794 : : }
1795 : :
1796 : : // set line and fill color
1797 : 0 : const sal_uInt16 nTransPercentVcl((sal_uInt16)basegfx::fround(rUniTransparenceCandidate.getTransparence() * 100.0));
1798 [ # # ]: 0 : mpOutputDevice->SetFillColor(Color(aPolygonColor));
1799 [ # # ]: 0 : mpOutputDevice->SetLineColor();
1800 : :
1801 : : // call VCL directly; encapsulate with SvtGraphicFill
1802 [ # # ]: 0 : impStartSvtGraphicFill(pSvtGraphicFill);
1803 : : mpOutputDevice->DrawTransparent(
1804 : : PolyPolygon(aLocalPolyPolygon),
1805 [ # # ][ # # ]: 0 : nTransPercentVcl);
[ # # ]
1806 [ # # ][ # # ]: 0 : impEndSvtGraphicFill(pSvtGraphicFill);
1807 : : }
1808 : : else
1809 : : {
1810 : : // svae old mfCurrentUnifiedTransparence and set new one
1811 : : // so that contained SvtGraphicStroke may use the current one
1812 : 0 : const double fLastCurrentUnifiedTransparence(mfCurrentUnifiedTransparence);
1813 : : // #i105377# paint the content metafile opaque as the transparency gets
1814 : : // split of into the gradient below
1815 : : // mfCurrentUnifiedTransparence = rUniTransparenceCandidate.getTransparence();
1816 : 0 : mfCurrentUnifiedTransparence = 0;
1817 : :
1818 : : // various content, create content-metafile
1819 [ # # ]: 0 : GDIMetaFile aContentMetafile;
1820 [ # # ]: 0 : const Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile));
1821 : :
1822 : : // restore mfCurrentUnifiedTransparence; it may have been used
1823 : : // while processing the sub-content in impDumpToMetaFile
1824 : 0 : mfCurrentUnifiedTransparence = fLastCurrentUnifiedTransparence;
1825 : :
1826 : : // create uniform VCL gradient for uniform transparency
1827 [ # # ]: 0 : Gradient aVCLGradient;
1828 : 0 : const sal_uInt8 nTransPercentVcl((sal_uInt8)basegfx::fround(rUniTransparenceCandidate.getTransparence() * 255.0));
1829 : 0 : const Color aTransColor(nTransPercentVcl, nTransPercentVcl, nTransPercentVcl);
1830 : :
1831 [ # # ]: 0 : aVCLGradient.SetStyle(GradientStyle_LINEAR);
1832 [ # # ]: 0 : aVCLGradient.SetStartColor(aTransColor);
1833 [ # # ]: 0 : aVCLGradient.SetEndColor(aTransColor);
1834 [ # # ]: 0 : aVCLGradient.SetAngle(0);
1835 [ # # ]: 0 : aVCLGradient.SetBorder(0);
1836 [ # # ]: 0 : aVCLGradient.SetOfsX(0);
1837 [ # # ]: 0 : aVCLGradient.SetOfsY(0);
1838 [ # # ]: 0 : aVCLGradient.SetStartIntensity(100);
1839 [ # # ]: 0 : aVCLGradient.SetEndIntensity(100);
1840 [ # # ]: 0 : aVCLGradient.SetSteps(2);
1841 : :
1842 : : // render it to VCL
1843 : : mpOutputDevice->DrawTransparent(
1844 : : aContentMetafile, aPrimitiveRectangle.TopLeft(),
1845 [ # # ][ # # ]: 0 : aPrimitiveRectangle.GetSize(), aVCLGradient);
[ # # ][ # # ]
1846 : : }
1847 : : }
1848 : : }
1849 : :
1850 [ # # ]: 0 : break;
1851 : : }
1852 : : case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D :
1853 : : {
1854 : : // for metafile: Need to examine what the pure vcl version is doing here actually
1855 : : // - uses DrawTransparent with metafile for content and a gradient
1856 : : // i can detect this here with checking the gradient part for a single
1857 : : // FillGradientPrimitive2D and reconstruct the gradient.
1858 : : // If that detection goes wrong, i have to create an transparence-blended bitmap. Eventually
1859 : : // do that in stripes, else RenderTransparencePrimitive2D may just be used
1860 : 0 : const primitive2d::TransparencePrimitive2D& rTransparenceCandidate = static_cast< const primitive2d::TransparencePrimitive2D& >(rCandidate);
1861 [ # # ]: 0 : const primitive2d::Primitive2DSequence rContent = rTransparenceCandidate.getChildren();
1862 [ # # ]: 0 : const primitive2d::Primitive2DSequence rTransparence = rTransparenceCandidate.getTransparence();
1863 : :
1864 [ # # ][ # # ]: 0 : if(rContent.hasElements() && rTransparence.hasElements())
[ # # ]
1865 : : {
1866 : : // try to identify a single FillGradientPrimitive2D in the
1867 : : // transparence part of the primitive
1868 : 0 : const primitive2d::FillGradientPrimitive2D* pFiGradient = 0;
1869 : : static bool bForceToBigTransparentVDev(false);
1870 : :
1871 [ # # ][ # # ]: 0 : if(!bForceToBigTransparentVDev && 1 == rTransparence.getLength())
[ # # ]
1872 : : {
1873 : 0 : const primitive2d::Primitive2DReference xReference(rTransparence[0]);
1874 [ # # ][ # # ]: 0 : pFiGradient = dynamic_cast< const primitive2d::FillGradientPrimitive2D* >(xReference.get());
1875 : : }
1876 : :
1877 : : // Check also for correct ID to exclude derived implementations
1878 [ # # ][ # # ]: 0 : if(pFiGradient && PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D == pFiGradient->getPrimitive2DID())
[ # # ][ # # ]
1879 : : {
1880 : : // various content, create content-metafile
1881 [ # # ]: 0 : GDIMetaFile aContentMetafile;
1882 [ # # ]: 0 : const Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile));
1883 : :
1884 : : // re-create a VCL-gradient from FillGradientPrimitive2D
1885 [ # # ]: 0 : Gradient aVCLGradient;
1886 [ # # ]: 0 : impConvertFillGradientAttributeToVCLGradient(aVCLGradient, pFiGradient->getFillGradient(), true);
1887 : :
1888 : : // render it to VCL
1889 : : mpOutputDevice->DrawTransparent(
1890 : : aContentMetafile, aPrimitiveRectangle.TopLeft(),
1891 [ # # ][ # # ]: 0 : aPrimitiveRectangle.GetSize(), aVCLGradient);
[ # # ][ # # ]
1892 : : }
1893 : : else
1894 : : {
1895 : : // sub-transparence group. Draw to VDev first.
1896 : : // this may get refined to tiling when resolution is too big here
1897 : :
1898 : : // need to avoid switching off MapMode stuff here; maybe need another
1899 : : // tooling class, cannot just do the same as with the pixel renderer.
1900 : : // Need to experiment...
1901 : :
1902 : : // Okay, basic implementation finished and tested. The DPI stuff was hard
1903 : : // and not easy to find out that it's needed.
1904 : : // Since this will not yet happen normally (as long as noone constructs
1905 : : // transparence primitives with non-trivial transparence content) i will for now not
1906 : : // refine to tiling here.
1907 : :
1908 [ # # ]: 0 : basegfx::B2DRange aViewRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
1909 [ # # ]: 0 : aViewRange.transform(maCurrentTransformation);
1910 : : const Rectangle aRectLogic(
1911 [ # # ][ # # ]: 0 : (sal_Int32)floor(aViewRange.getMinX()), (sal_Int32)floor(aViewRange.getMinY()),
1912 [ # # ][ # # ]: 0 : (sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY()));
[ # # ]
1913 [ # # ]: 0 : const Rectangle aRectPixel(mpOutputDevice->LogicToPixel(aRectLogic));
1914 [ # # ]: 0 : const Size aSizePixel(aRectPixel.GetSize());
1915 : 0 : const Point aEmptyPoint;
1916 [ # # ]: 0 : VirtualDevice aBufferDevice;
1917 : :
1918 [ # # ][ # # ]: 0 : if(aBufferDevice.SetOutputSizePixel(aSizePixel))
1919 : : {
1920 : : // create and set MapModes for target devices
1921 [ # # ]: 0 : MapMode aNewMapMode(mpOutputDevice->GetMapMode());
1922 [ # # ]: 0 : aNewMapMode.SetOrigin(Point(-aRectLogic.Left(), -aRectLogic.Top()));
1923 [ # # ]: 0 : aBufferDevice.SetMapMode(aNewMapMode);
1924 : :
1925 : : // prepare view transformation for target renderers
1926 : : // ATTENTION! Need to apply another scaling because of the potential DPI differences
1927 : : // between Printer and VDev (mpOutputDevice and aBufferDevice here).
1928 : : // To get the DPI, LogicToPixel from (1,1) from MAP_INCH needs to be used.
1929 [ # # ]: 0 : basegfx::B2DHomMatrix aViewTransform(aBufferDevice.GetViewTransformation());
1930 [ # # ][ # # ]: 0 : const Size aDPIOld(mpOutputDevice->LogicToPixel(Size(1, 1), MAP_INCH));
[ # # ]
1931 [ # # ][ # # ]: 0 : const Size aDPINew(aBufferDevice.LogicToPixel(Size(1, 1), MAP_INCH));
[ # # ]
1932 : 0 : const double fDPIXChange((double)aDPIOld.getWidth() / (double)aDPINew.getWidth());
1933 : 0 : const double fDPIYChange((double)aDPIOld.getHeight() / (double)aDPINew.getHeight());
1934 : :
1935 [ # # ][ # # ]: 0 : if(!basegfx::fTools::equal(fDPIXChange, 1.0) || !basegfx::fTools::equal(fDPIYChange, 1.0))
[ # # ][ # # ]
[ # # ]
1936 : : {
1937 [ # # ]: 0 : aViewTransform.scale(fDPIXChange, fDPIYChange);
1938 : : }
1939 : :
1940 : : // create view information and pixel renderer. Reuse known ViewInformation
1941 : : // except new transformation and range
1942 : : const geometry::ViewInformation2D aViewInfo(
1943 [ # # ]: 0 : getViewInformation2D().getObjectTransformation(),
1944 : : aViewTransform,
1945 : : aViewRange,
1946 [ # # ]: 0 : getViewInformation2D().getVisualizedPage(),
1947 : 0 : getViewInformation2D().getViewTime(),
1948 [ # # # # ]: 0 : getViewInformation2D().getExtendedInformationSequence());
[ # # ]
1949 : :
1950 [ # # ]: 0 : VclPixelProcessor2D aBufferProcessor(aViewInfo, aBufferDevice);
1951 : :
1952 : : // draw content using pixel renderer
1953 [ # # ]: 0 : aBufferProcessor.process(rContent);
1954 [ # # ]: 0 : const Bitmap aBmContent(aBufferDevice.GetBitmap(aEmptyPoint, aSizePixel));
1955 : :
1956 : : // draw transparence using pixel renderer
1957 [ # # ]: 0 : aBufferDevice.Erase();
1958 [ # # ]: 0 : aBufferProcessor.process(rTransparence);
1959 [ # # ][ # # ]: 0 : const AlphaMask aBmAlpha(aBufferDevice.GetBitmap(aEmptyPoint, aSizePixel));
[ # # ]
1960 : :
1961 : : // paint
1962 : : mpOutputDevice->DrawBitmapEx(
1963 : : aRectLogic.TopLeft(),
1964 : : aRectLogic.GetSize(),
1965 [ # # ][ # # ]: 0 : BitmapEx(aBmContent, aBmAlpha));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1966 [ # # ]: 0 : }
1967 : : }
1968 : : }
1969 : :
1970 [ # # ][ # # ]: 0 : break;
1971 : : }
1972 : : case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
1973 : : {
1974 : : // use default transform group pocessing
1975 : 0 : RenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
1976 : 0 : break;
1977 : : }
1978 : : case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
1979 : : {
1980 : : // new XDrawPage for ViewInformation2D
1981 : 0 : RenderPagePreviewPrimitive2D(static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate));
1982 : 0 : break;
1983 : : }
1984 : : case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
1985 : : {
1986 : : // use default marker array pocessing
1987 : 0 : RenderMarkerArrayPrimitive2D(static_cast< const primitive2d::MarkerArrayPrimitive2D& >(rCandidate));
1988 : 0 : break;
1989 : : }
1990 : : case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
1991 : : {
1992 : : // use default point array pocessing
1993 : 0 : RenderPointArrayPrimitive2D(static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate));
1994 : 0 : break;
1995 : : }
1996 : : case PRIMITIVE2D_ID_CHARTPRIMITIVE2D :
1997 : : {
1998 : : // ChartPrimitive2D
1999 : 0 : const primitive2d::ChartPrimitive2D& rChartPrimitive = static_cast< const primitive2d::ChartPrimitive2D& >(rCandidate);
2000 : :
2001 [ # # ]: 0 : if(!renderChartPrimitive2D(
2002 : : rChartPrimitive,
2003 : : *mpOutputDevice,
2004 : 0 : getViewInformation2D()))
2005 : : {
2006 : : // fallback to decomposition (MetaFile)
2007 [ # # ]: 0 : process(rChartPrimitive.get2DDecomposition(getViewInformation2D()));
2008 : : }
2009 : 0 : break;
2010 : : }
2011 : : case PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D :
2012 : : {
2013 : : // structured tag primitive
2014 : 0 : const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate = static_cast< const primitive2d::StructureTagPrimitive2D& >(rCandidate);
2015 : 0 : const vcl::PDFWriter::StructElement& rTagElement(rStructureTagCandidate.getStructureElement());
2016 : 0 : const bool bTagUsed(vcl::PDFWriter::NonStructElement != rTagElement);
2017 : :
2018 [ # # ][ # # ]: 0 : if(mpPDFExtOutDevData && bTagUsed)
2019 : : {
2020 : : // write start tag
2021 [ # # ]: 0 : mpPDFExtOutDevData->BeginStructureElement(rTagElement);
2022 : : }
2023 : :
2024 : : // proccess children normally
2025 : 0 : process(rStructureTagCandidate.getChildren());
2026 : :
2027 [ # # ][ # # ]: 0 : if(mpPDFExtOutDevData && bTagUsed)
2028 : : {
2029 : : // write end tag
2030 : 0 : mpPDFExtOutDevData->EndStructureElement();
2031 : : }
2032 : :
2033 : 0 : break;
2034 : : }
2035 : : case PRIMITIVE2D_ID_EPSPRIMITIVE2D :
2036 : : {
2037 : 0 : RenderEpsPrimitive2D(static_cast< const primitive2d::EpsPrimitive2D& >(rCandidate));
2038 : 0 : break;
2039 : : }
2040 : : default :
2041 : : {
2042 : : // process recursively
2043 [ + - ]: 15713 : process(rCandidate.get2DDecomposition(getViewInformation2D()));
2044 : 15713 : break;
2045 : : }
2046 : : }
2047 : 49334 : }
2048 : : } // end of namespace processor2d
2049 [ + - ][ + - ]: 735 : } // end of namespace drawinglayer
2050 : :
2051 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|