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/canvasprocessor.hxx>
30 : : #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
31 : : #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
32 : : #include <com/sun/star/rendering/XCanvas.hpp>
33 : : #include <vcl/canvastools.hxx>
34 : : #include <basegfx/tools/canvastools.hxx>
35 : : #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
36 : : #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
37 : : #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
38 : : #include <canvas/canvastools.hxx>
39 : : #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
40 : : #include <basegfx/polygon/b2dpolygonclipper.hxx>
41 : : #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
42 : : #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
43 : : #include <cppcanvas/basegfxfactory.hxx>
44 : : #include <com/sun/star/rendering/XBitmapCanvas.hpp>
45 : : #include <cppcanvas/vclfactory.hxx>
46 : : #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
47 : : #include <drawinglayer/primitive2d/textprimitive2d.hxx>
48 : : #include <com/sun/star/rendering/TextDirection.hpp>
49 : : #include <vclhelperbitmaptransform.hxx>
50 : : #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
51 : : #include <basegfx/polygon/b2dpolygontools.hxx>
52 : : #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
53 : : #include <basegfx/tuple/b2i64tuple.hxx>
54 : : #include <basegfx/range/b2irange.hxx>
55 : : #include <com/sun/star/rendering/XIntegerReadOnlyBitmap.hpp>
56 : : #include <com/sun/star/rendering/PanoseProportion.hpp>
57 : : #include <com/sun/star/rendering/CompositeOperation.hpp>
58 : : #include <com/sun/star/rendering/StrokeAttributes.hpp>
59 : : #include <com/sun/star/rendering/PathJoinType.hpp>
60 : : #include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
61 : : #include <com/sun/star/rendering/TexturingMode.hpp>
62 : : #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
63 : : #include <vclhelperbufferdevice.hxx>
64 : : #include <drawinglayer/primitive2d/chartprimitive2d.hxx>
65 : : #include <helperchartrenderer.hxx>
66 : : #include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
67 : : #include <helperwrongspellrenderer.hxx>
68 : : #include <basegfx/matrix/b2dhommatrixtools.hxx>
69 : :
70 : : #include "getdigitlanguage.hxx"
71 : :
72 : : //////////////////////////////////////////////////////////////////////////////
73 : :
74 : : using namespace com::sun::star;
75 : :
76 : : //////////////////////////////////////////////////////////////////////////////
77 : :
78 : : namespace drawinglayer
79 : : {
80 : : namespace processor2d
81 : : {
82 : : //////////////////////////////////////////////////////////////////////////////
83 : : // single primitive renderers
84 : :
85 : 0 : void canvasProcessor2D::impRenderMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate)
86 : : {
87 : 0 : const primitive2d::Primitive2DSequence& rChildren = rMaskCandidate.getChildren();
88 : : static bool bUseMaskBitmapMethod(true);
89 : :
90 [ # # ]: 0 : if(rChildren.hasElements())
91 : : {
92 [ # # ]: 0 : basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
93 : :
94 [ # # ][ # # ]: 0 : if(!aMask.count())
95 : : {
96 : : // no mask, no clipping. recursively paint content
97 [ # # ]: 0 : process(rChildren);
98 : : }
99 : : else
100 : : {
101 : : // there are principally two methods for implementing the mask primitive. One
102 : : // is to set a clip polygon at the canvas, the other is to create and use a
103 : : // transparence-using XBitmap for content and draw the mask as transparence. Both have their
104 : : // advantages and disadvantages, so here are both with a bool allowing simple
105 : : // change
106 [ # # ]: 0 : if(bUseMaskBitmapMethod)
107 : : {
108 : : // get logic range of transparent part, clip with ViewRange
109 [ # # ]: 0 : basegfx::B2DRange aLogicRange(aMask.getB2DRange());
110 : :
111 [ # # ][ # # ]: 0 : if(!getViewInformation2D().getViewport().isEmpty())
[ # # ]
112 : : {
113 [ # # ][ # # ]: 0 : aLogicRange.intersect(getViewInformation2D().getViewport());
114 : : }
115 : :
116 [ # # ][ # # ]: 0 : if(!aLogicRange.isEmpty())
117 : : {
118 : : // get discrete range of transparent part
119 : 0 : basegfx::B2DRange aDiscreteRange(aLogicRange);
120 [ # # ][ # # ]: 0 : aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation());
121 : :
122 : : // expand to next covering discrete values (pixel bounds)
123 [ # # ][ # # ]: 0 : aDiscreteRange.expand(basegfx::B2DTuple(floor(aDiscreteRange.getMinX()), floor(aDiscreteRange.getMinY())));
[ # # ]
124 [ # # ][ # # ]: 0 : aDiscreteRange.expand(basegfx::B2DTuple(ceil(aDiscreteRange.getMaxX()), ceil(aDiscreteRange.getMaxY())));
[ # # ]
125 : :
126 : : // use VCL-based buffer device
127 [ # # ]: 0 : impBufferDevice aBufferDevice(*mpOutputDevice, aDiscreteRange, false);
128 : :
129 [ # # ][ # # ]: 0 : if(aBufferDevice.isVisible())
130 : : {
131 : : // remember current OutDev, Canvas and ViewInformation
132 : 0 : OutputDevice* pLastOutputDevice = mpOutputDevice;
133 : 0 : uno::Reference< rendering::XCanvas > xLastCanvas(mxCanvas);
134 [ # # ]: 0 : const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
135 : :
136 : : // prepare discrete offset for XBitmap, do not forget that the buffer bitmap
137 : : // may be truncated to discrete visible pixels
138 : : const basegfx::B2DHomMatrix aDiscreteOffset(basegfx::tools::createTranslateB2DHomMatrix(
139 [ # # ][ # # ]: 0 : aDiscreteRange.getMinX() > 0.0 ? -aDiscreteRange.getMinX() : 0.0,
140 [ # # ][ # # ]: 0 : aDiscreteRange.getMinY() > 0.0 ? -aDiscreteRange.getMinY() : 0.0));
[ # # ][ # # ]
[ # # ]
141 : :
142 : : // create new local ViewInformation2D with new transformation
143 : : const geometry::ViewInformation2D aViewInformation2D(
144 [ # # ]: 0 : getViewInformation2D().getObjectTransformation(),
145 [ # # ]: 0 : aDiscreteOffset * getViewInformation2D().getViewTransformation(),
146 [ # # ]: 0 : getViewInformation2D().getViewport(),
147 [ # # ]: 0 : getViewInformation2D().getVisualizedPage(),
148 : 0 : getViewInformation2D().getViewTime(),
149 [ # # # # ]: 0 : getViewInformation2D().getExtendedInformationSequence());
[ # # ][ # # ]
[ # # ]
150 [ # # ]: 0 : updateViewInformation(aViewInformation2D);
151 : :
152 : : // set OutDev and Canvas to content target
153 : 0 : mpOutputDevice = &aBufferDevice.getContent();
154 [ # # ][ # # ]: 0 : mxCanvas = mpOutputDevice->GetCanvas();
155 [ # # ][ # # ]: 0 : canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
156 : :
157 : : // if ViewState transform is changed, the clipping polygon needs to be adapted, too
158 [ # # ]: 0 : const basegfx::B2DPolyPolygon aOldClipPolyPolygon(maClipPolyPolygon);
159 : :
160 [ # # ][ # # ]: 0 : if(maClipPolyPolygon.count())
161 : : {
162 [ # # ]: 0 : maClipPolyPolygon.transform(aDiscreteOffset);
163 [ # # ][ # # ]: 0 : maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
[ # # ][ # # ]
164 : : }
165 : :
166 : : // paint content
167 [ # # ]: 0 : process(rChildren);
168 : :
169 : : // draw mask
170 : 0 : const basegfx::BColor aBlack(0.0, 0.0, 0.0);
171 [ # # ][ # # ]: 0 : maRenderState.DeviceColor = aBlack.colorToDoubleSequence(mxCanvas->getDevice());
[ # # ][ # # ]
[ # # ]
172 : :
173 [ # # ][ # # ]: 0 : if(getOptionsDrawinglayer().IsAntiAliasing())
174 : : {
175 : : // with AA, use 8bit AlphaMask to get nice borders
176 [ # # ]: 0 : VirtualDevice& rTransparence = aBufferDevice.getTransparence();
177 [ # # ][ # # ]: 0 : rTransparence.GetCanvas()->fillPolyPolygon(
178 [ # # ]: 0 : basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), aMask),
179 [ # # ][ # # ]: 0 : maViewState, maRenderState);
[ # # ]
180 : : }
181 : : else
182 : : {
183 : : // No AA, use 1bit mask
184 [ # # ]: 0 : VirtualDevice& rMask = aBufferDevice.getMask();
185 [ # # ][ # # ]: 0 : rMask.GetCanvas()->fillPolyPolygon(
186 [ # # ]: 0 : basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), aMask),
187 [ # # ][ # # ]: 0 : maViewState, maRenderState);
[ # # ]
188 : : }
189 : :
190 : : // back to old color stack, OutDev, Canvas and ViewTransform
191 : 0 : mpOutputDevice = pLastOutputDevice;
192 [ # # ]: 0 : mxCanvas = xLastCanvas;
193 [ # # ]: 0 : updateViewInformation(aLastViewInformation2D);
194 [ # # ][ # # ]: 0 : canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
195 : :
196 : : // restore clipping polygon
197 [ # # ]: 0 : maClipPolyPolygon = aOldClipPolyPolygon;
198 : :
199 [ # # ][ # # ]: 0 : if(maClipPolyPolygon.count())
200 : : {
201 [ # # ][ # # ]: 0 : maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
[ # # ][ # # ]
202 : : }
203 : :
204 : : // dump buffer to outdev
205 [ # # ][ # # ]: 0 : aBufferDevice.paint();
[ # # ][ # # ]
[ # # ]
206 [ # # ]: 0 : }
207 : : }
208 : : }
209 : : else
210 : : {
211 : : // transform new mask polygon to view coordinates for processing. All masks
212 : : // are processed in view coordinates and clipped against each other evtl. to
213 : : // create multi-clips
214 [ # # ][ # # ]: 0 : aMask.transform(getViewInformation2D().getObjectTransformation());
215 : :
216 : : // remember last current clip polygon
217 [ # # ]: 0 : const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon);
218 : :
219 [ # # ][ # # ]: 0 : if(maClipPolyPolygon.count())
220 : : {
221 : : // there is already a clip polygon set; build clipped union of
222 : : // current mask polygon and new one
223 [ # # ][ # # ]: 0 : maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(aMask, maClipPolyPolygon, false, false);
[ # # ]
224 : : }
225 : : else
226 : : {
227 : : // use mask directly
228 [ # # ]: 0 : maClipPolyPolygon = aMask;
229 : : }
230 : :
231 : : // set at ViewState
232 [ # # ][ # # ]: 0 : if(maClipPolyPolygon.count())
233 : : {
234 : : // set new as clip polygon
235 [ # # ][ # # ]: 0 : maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
[ # # ][ # # ]
236 : : }
237 : : else
238 : : {
239 : : // empty, reset
240 : 0 : maViewState.Clip.clear();
241 : : }
242 : :
243 : : // paint content
244 [ # # ]: 0 : process(rChildren);
245 : :
246 : : // restore local current to rescued clip polygon
247 [ # # ]: 0 : maClipPolyPolygon = aLastClipPolyPolygon;
248 : :
249 : : // set at ViewState
250 [ # # ][ # # ]: 0 : if(maClipPolyPolygon.count())
251 : : {
252 : : // set new as clip polygon
253 [ # # ][ # # ]: 0 : maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
[ # # ][ # # ]
254 : : }
255 : : else
256 : : {
257 : : // empty, reset
258 : 0 : maViewState.Clip.clear();
259 [ # # ]: 0 : }
260 : : }
261 [ # # ]: 0 : }
262 : : }
263 : 0 : }
264 : :
265 : 0 : void canvasProcessor2D::impRenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rMetaCandidate)
266 : : {
267 [ # # ]: 0 : GDIMetaFile aMetaFile;
268 : :
269 [ # # ]: 0 : if(maBColorModifierStack.count())
270 : : {
271 : 0 : const basegfx::BColor aRGBBaseColor(0, 0, 0);
272 [ # # ]: 0 : const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor));
273 [ # # ][ # # ]: 0 : aMetaFile = rMetaCandidate.getMetaFile().GetMonochromeMtf(Color(aRGBColor));
[ # # ]
274 : : }
275 : : else
276 : : {
277 [ # # ]: 0 : aMetaFile = rMetaCandidate.getMetaFile();
278 : : }
279 : :
280 [ # # ]: 0 : cppcanvas::BitmapCanvasSharedPtr pCanvas(cppcanvas::VCLFactory::getInstance().createCanvas(
281 [ # # ][ # # ]: 0 : uno::Reference<rendering::XBitmapCanvas>(mxCanvas, uno::UNO_QUERY_THROW)));
282 [ # # ]: 0 : cppcanvas::RendererSharedPtr pMtfRenderer(cppcanvas::VCLFactory::getInstance().createRenderer(
283 [ # # ][ # # ]: 0 : pCanvas, aMetaFile, cppcanvas::Renderer::Parameters()));
[ # # ][ # # ]
[ # # ]
284 : :
285 [ # # ]: 0 : if(pMtfRenderer)
286 : : {
287 [ # # ][ # # ]: 0 : pCanvas->setTransformation(getViewInformation2D().getObjectToViewTransformation());
288 [ # # ]: 0 : pMtfRenderer->setTransformation(rMetaCandidate.getTransform());
289 [ # # ]: 0 : pMtfRenderer->draw();
290 [ # # ][ # # ]: 0 : }
[ # # ]
291 : 0 : }
292 : :
293 : 0 : void canvasProcessor2D::impRenderTextSimplePortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate)
294 : : {
295 [ # # ]: 0 : if(rTextCandidate.getTextLength())
296 : : {
297 : 0 : double fShearX(0.0);
298 : : {
299 [ # # ][ # # ]: 0 : const basegfx::B2DHomMatrix aLocalTransform(getViewInformation2D().getObjectToViewTransformation() * rTextCandidate.getTextTransform());
300 : 0 : basegfx::B2DVector aScale, aTranslate;
301 : : double fRotate;
302 [ # # ][ # # ]: 0 : aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
303 : : }
304 : :
305 [ # # ]: 0 : if(!basegfx::fTools::equalZero(fShearX))
306 : : {
307 : : // text is sheared. As long as the canvas renderers do not support this,
308 : : // use the decomposed primitive
309 [ # # ][ # # ]: 0 : process(rTextCandidate.get2DDecomposition(getViewInformation2D()));
[ # # ]
310 : : }
311 : : else
312 : : {
313 : 0 : const attribute::FontAttribute& rFontAttr(rTextCandidate.getFontAttribute());
314 : 0 : rendering::FontRequest aFontRequest;
315 : :
316 [ # # ][ # # ]: 0 : aFontRequest.FontDescription.FamilyName = rFontAttr.getFamilyName();
317 [ # # ][ # # ]: 0 : aFontRequest.FontDescription.StyleName = rFontAttr.getStyleName();
318 [ # # ][ # # ]: 0 : aFontRequest.FontDescription.IsSymbolFont = rFontAttr.getSymbol() ? util::TriState_YES : util::TriState_NO;
319 [ # # ][ # # ]: 0 : aFontRequest.FontDescription.IsVertical = rFontAttr.getVertical() ? util::TriState_YES : util::TriState_NO;
320 : : // TODO(F2): improve vclenum->panose conversion
321 [ # # ]: 0 : aFontRequest.FontDescription.FontDescription.Weight = static_cast< sal_uInt8 >(rFontAttr.getWeight());
322 : : aFontRequest.FontDescription.FontDescription.Proportion =
323 [ # # ]: 0 : rFontAttr.getMonospaced()
324 : : ? rendering::PanoseProportion::MONO_SPACED
325 [ # # ]: 0 : : rendering::PanoseProportion::ANYTHING;
326 [ # # ][ # # ]: 0 : aFontRequest.FontDescription.FontDescription.Letterform = rFontAttr.getItalic() ? 9 : 0;
327 : :
328 : : // init CellSize to 1.0, else a default font height will be used
329 : 0 : aFontRequest.CellSize = 1.0;
330 : 0 : aFontRequest.Locale = rTextCandidate.getLocale();
331 : :
332 : : // font matrix should only be used for glyph rotations etc.
333 : 0 : com::sun::star::geometry::Matrix2D aFontMatrix;
334 [ # # ]: 0 : canvas::tools::setIdentityMatrix2D(aFontMatrix);
335 : :
336 [ # # ]: 0 : uno::Reference<rendering::XCanvasFont> xFont(mxCanvas->createFont(
337 [ # # ][ # # ]: 0 : aFontRequest, uno::Sequence< beans::PropertyValue >(), aFontMatrix));
[ # # ]
338 : :
339 [ # # ]: 0 : if(xFont.is())
340 : : {
341 : : // got a font, now try to get a TextLayout
342 : : const rendering::StringContext aStringContext(
343 [ # # ]: 0 : rTextCandidate.getText(), rTextCandidate.getTextPosition(), rTextCandidate.getTextLength());
344 [ # # ]: 0 : uno::Reference<rendering::XTextLayout> xLayout(xFont->createTextLayout(
345 [ # # ]: 0 : aStringContext, com::sun::star::rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0));
346 : :
347 [ # # ]: 0 : if(xLayout.is())
348 : : {
349 : : // got a text layout, apply DXArray if given
350 : 0 : const ::std::vector< double >& rDXArray = rTextCandidate.getDXArray();
351 : 0 : const sal_uInt32 nDXCount(rDXArray.size());
352 : :
353 [ # # ]: 0 : if(nDXCount)
354 : : {
355 : : // DXArray does not need to be adapted to getTextPosition/getTextLength,
356 : : // it is already provided correctly
357 [ # # ][ # # ]: 0 : const uno::Sequence< double > aDXSequence(&rDXArray[0], nDXCount);
358 [ # # ][ # # ]: 0 : xLayout->applyLogicalAdvancements(aDXSequence);
[ # # ]
359 : : }
360 : :
361 : : // set text color
362 [ # # ]: 0 : const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rTextCandidate.getFontColor()));
363 [ # # ][ # # ]: 0 : maRenderState.DeviceColor = aRGBColor.colorToDoubleSequence(mxCanvas->getDevice());
[ # # ][ # # ]
[ # # ]
364 : :
365 : : // set text transformation
366 : : canvas::tools::setRenderStateTransform(maRenderState,
367 [ # # ][ # # ]: 0 : getViewInformation2D().getObjectTransformation() * rTextCandidate.getTextTransform());
[ # # ][ # # ]
368 : :
369 : : // paint
370 [ # # ][ # # ]: 0 : mxCanvas->drawTextLayout(xLayout, maViewState, maRenderState);
371 : 0 : }
372 : 0 : }
373 : : }
374 : : }
375 : 0 : }
376 : :
377 : 0 : void canvasProcessor2D::impRenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
378 : : {
379 : : // apply possible color modification to BitmapEx
380 [ # # ]: 0 : BitmapEx aModifiedBitmapEx(impModifyBitmapEx(maBColorModifierStack, rBitmapCandidate.getBitmapEx()));
381 : :
382 [ # # ][ # # ]: 0 : if(aModifiedBitmapEx.IsEmpty())
383 : : {
384 : : // replace with color filled polygon
385 [ # # ]: 0 : const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
386 [ # # ]: 0 : const basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon());
387 : :
388 [ # # ][ # # ]: 0 : maRenderState.DeviceColor = aModifiedColor.colorToDoubleSequence(mxCanvas->getDevice());
[ # # ][ # # ]
[ # # ]
389 : : canvas::tools::setRenderStateTransform(maRenderState,
390 [ # # ][ # # ]: 0 : getViewInformation2D().getObjectTransformation() * rBitmapCandidate.getTransform());
[ # # ][ # # ]
391 : :
392 [ # # ]: 0 : mxCanvas->fillPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
393 [ # # ][ # # ]: 0 : mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aPolygon)), maViewState, maRenderState);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
394 : : }
395 : : else
396 : : {
397 : : // adapt object's transformation to the correct scale
398 : 0 : basegfx::B2DVector aScale, aTranslate;
399 : 0 : const Size aSizePixel(aModifiedBitmapEx.GetSizePixel());
400 : :
401 [ # # ][ # # ]: 0 : if(0 != aSizePixel.Width() && 0 != aSizePixel.Height())
[ # # ]
402 : : {
403 : : double fRotate, fShearX;
404 [ # # ]: 0 : rBitmapCandidate.getTransform().decompose(aScale, aTranslate, fRotate, fShearX);
405 : : const basegfx::B2DHomMatrix aNewMatrix(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
406 : 0 : aScale.getX() / aSizePixel.Width(), aScale.getY() / aSizePixel.Height(),
407 [ # # ]: 0 : fShearX, fRotate, aTranslate.getX(), aTranslate.getY()));
408 : :
409 : : canvas::tools::setRenderStateTransform(maRenderState,
410 [ # # ][ # # ]: 0 : getViewInformation2D().getObjectTransformation() * aNewMatrix);
[ # # ][ # # ]
411 : :
412 [ # # ]: 0 : mxCanvas->drawBitmap(
413 [ # # ]: 0 : vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(), aModifiedBitmapEx),
414 [ # # ][ # # ]: 0 : maViewState, maRenderState);
[ # # ][ # # ]
415 : 0 : }
416 [ # # ]: 0 : }
417 : 0 : }
418 : :
419 : 0 : void canvasProcessor2D::impRenderTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D& rTransparenceCandidate)
420 : : {
421 : 0 : const primitive2d::Primitive2DSequence& rChildren = rTransparenceCandidate.getChildren();
422 : 0 : const primitive2d::Primitive2DSequence& rTransparence = rTransparenceCandidate.getTransparence();
423 : :
424 [ # # ][ # # ]: 0 : if(rChildren.hasElements() && rTransparence.hasElements())
[ # # ]
425 : : {
426 : : // get logic range of transparent part and clip with ViewRange
427 [ # # ]: 0 : basegfx::B2DRange aLogicRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rChildren, getViewInformation2D()));
428 : :
429 [ # # ][ # # ]: 0 : if(!getViewInformation2D().getViewport().isEmpty())
[ # # ]
430 : : {
431 [ # # ][ # # ]: 0 : aLogicRange.intersect(getViewInformation2D().getViewport());
432 : : }
433 : :
434 [ # # ][ # # ]: 0 : if(!aLogicRange.isEmpty())
435 : : {
436 : : // get discrete range of transparent part
437 : 0 : basegfx::B2DRange aDiscreteRange(aLogicRange);
438 [ # # ][ # # ]: 0 : aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation());
439 : :
440 : : // expand to next covering discrete values (pixel bounds)
441 [ # # ][ # # ]: 0 : aDiscreteRange.expand(basegfx::B2DTuple(floor(aDiscreteRange.getMinX()), floor(aDiscreteRange.getMinY())));
[ # # ]
442 [ # # ][ # # ]: 0 : aDiscreteRange.expand(basegfx::B2DTuple(ceil(aDiscreteRange.getMaxX()), ceil(aDiscreteRange.getMaxY())));
[ # # ]
443 : :
444 : : // use VCL-based buffer device
445 [ # # ]: 0 : impBufferDevice aBufferDevice(*mpOutputDevice, aDiscreteRange, false);
446 : :
447 [ # # ][ # # ]: 0 : if(aBufferDevice.isVisible())
448 : : {
449 : : // remember current OutDev, Canvas and ViewInformation
450 : 0 : OutputDevice* pLastOutputDevice = mpOutputDevice;
451 : 0 : uno::Reference< rendering::XCanvas > xLastCanvas(mxCanvas);
452 [ # # ]: 0 : const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
453 : :
454 : : // prepare discrete offset for XBitmap, do not forget that the buffer bitmap
455 : : // may be truncated to discrete visible pixels
456 : : const basegfx::B2DHomMatrix aDiscreteOffset(basegfx::tools::createTranslateB2DHomMatrix(
457 [ # # ][ # # ]: 0 : aDiscreteRange.getMinX() > 0.0 ? -aDiscreteRange.getMinX() : 0.0,
458 [ # # ][ # # ]: 0 : aDiscreteRange.getMinY() > 0.0 ? -aDiscreteRange.getMinY() : 0.0));
[ # # ][ # # ]
[ # # ]
459 : :
460 : : // create new local ViewInformation2D with new transformation
461 : : const geometry::ViewInformation2D aViewInformation2D(
462 [ # # ]: 0 : getViewInformation2D().getObjectTransformation(),
463 [ # # ]: 0 : aDiscreteOffset * getViewInformation2D().getViewTransformation(),
464 [ # # ]: 0 : getViewInformation2D().getViewport(),
465 [ # # ]: 0 : getViewInformation2D().getVisualizedPage(),
466 : 0 : getViewInformation2D().getViewTime(),
467 [ # # # # ]: 0 : getViewInformation2D().getExtendedInformationSequence());
[ # # ][ # # ]
[ # # ]
468 [ # # ]: 0 : updateViewInformation(aViewInformation2D);
469 : :
470 : : // set OutDev and Canvas to content target
471 : 0 : mpOutputDevice = &aBufferDevice.getContent();
472 [ # # ][ # # ]: 0 : mxCanvas = mpOutputDevice->GetCanvas();
473 [ # # ][ # # ]: 0 : canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
474 : :
475 : : // if ViewState transform is changed, the clipping polygon needs to be adapted, too
476 [ # # ]: 0 : const basegfx::B2DPolyPolygon aOldClipPolyPolygon(maClipPolyPolygon);
477 : :
478 [ # # ][ # # ]: 0 : if(maClipPolyPolygon.count())
479 : : {
480 [ # # ]: 0 : maClipPolyPolygon.transform(aDiscreteOffset);
481 [ # # ][ # # ]: 0 : maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
[ # # ][ # # ]
482 : : }
483 : :
484 : : // paint content
485 [ # # ]: 0 : process(rChildren);
486 : :
487 : : // set to mask
488 [ # # ]: 0 : mpOutputDevice = &aBufferDevice.getTransparence();
489 [ # # ][ # # ]: 0 : mxCanvas = mpOutputDevice->GetCanvas();
490 [ # # ][ # # ]: 0 : canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
491 : :
492 : : // when painting transparence masks, reset the color stack
493 [ # # ]: 0 : basegfx::BColorModifierStack aLastBColorModifierStack(maBColorModifierStack);
494 [ # # ]: 0 : maBColorModifierStack = basegfx::BColorModifierStack();
495 : :
496 : : // paint mask to it (always with transparence intensities, evtl. with AA)
497 [ # # ]: 0 : process(rTransparence);
498 : :
499 : : // back to old color stack, OutDev, Canvas and ViewTransform
500 [ # # ]: 0 : maBColorModifierStack = aLastBColorModifierStack;
501 : 0 : mpOutputDevice = pLastOutputDevice;
502 [ # # ]: 0 : mxCanvas = xLastCanvas;
503 [ # # ]: 0 : updateViewInformation(aLastViewInformation2D);
504 [ # # ][ # # ]: 0 : canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
505 : :
506 : : // restore clipping polygon
507 [ # # ]: 0 : maClipPolyPolygon = aOldClipPolyPolygon;
508 : :
509 [ # # ][ # # ]: 0 : if(maClipPolyPolygon.count())
510 : : {
511 [ # # ][ # # ]: 0 : maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
[ # # ][ # # ]
512 : : }
513 : :
514 : : // dump buffer to outdev
515 [ # # ][ # # ]: 0 : aBufferDevice.paint();
[ # # ][ # # ]
[ # # ]
516 [ # # ]: 0 : }
517 : : }
518 : : }
519 : 0 : }
520 : :
521 : 0 : void canvasProcessor2D::impRenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive)
522 : : {
523 : : // support direct fat line geometry. This moves the decomposition to the canvas.
524 : : // As long as our canvases are used (which also use basegfx tooling) this makes
525 : : // no difference, but potentially canvases may better support this
526 : : static bool bSupportFatLineDirectly(true);
527 : 0 : bool bOutputDone(false);
528 : :
529 [ # # ]: 0 : if(bSupportFatLineDirectly)
530 : : {
531 : 0 : const attribute::LineAttribute& rLineAttribute = rPolygonStrokePrimitive.getLineAttribute();
532 : 0 : const attribute::StrokeAttribute& rStrokeAttribute = rPolygonStrokePrimitive.getStrokeAttribute();
533 : :
534 [ # # ][ # # ]: 0 : if(0.0 < rLineAttribute.getWidth() || 0 != rStrokeAttribute.getDotDashArray().size())
[ # # ]
535 : : {
536 [ # # ]: 0 : rendering::StrokeAttributes aStrokeAttribute;
537 : :
538 [ # # ]: 0 : aStrokeAttribute.StrokeWidth = rLineAttribute.getWidth();
539 : 0 : aStrokeAttribute.MiterLimit = 15.0; // degrees; maybe here (15.0 * F_PI180) is needed, not clear in the documentation
540 [ # # ]: 0 : const ::std::vector< double >& rDotDashArray = rStrokeAttribute.getDotDashArray();
541 : :
542 [ # # ]: 0 : if(!rDotDashArray.empty())
543 : : {
544 [ # # ][ # # ]: 0 : aStrokeAttribute.DashArray = uno::Sequence< double >(&rDotDashArray[0], rDotDashArray.size());
[ # # ][ # # ]
545 : : }
546 : :
547 [ # # ]: 0 : switch(rLineAttribute.getLineJoin())
[ # # # # ]
548 : : {
549 : : default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE
550 : 0 : aStrokeAttribute.JoinType = rendering::PathJoinType::NONE;
551 : 0 : break;
552 : : case basegfx::B2DLINEJOIN_BEVEL:
553 : 0 : aStrokeAttribute.JoinType = rendering::PathJoinType::BEVEL;
554 : 0 : break;
555 : : case basegfx::B2DLINEJOIN_MITER:
556 : 0 : aStrokeAttribute.JoinType = rendering::PathJoinType::MITER;
557 : 0 : break;
558 : : case basegfx::B2DLINEJOIN_ROUND:
559 : 0 : aStrokeAttribute.JoinType = rendering::PathJoinType::ROUND;
560 : 0 : break;
561 : : }
562 : :
563 [ # # ][ # # ]: 0 : const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLineAttribute.getColor()));
564 [ # # ][ # # ]: 0 : maRenderState.DeviceColor = aHairlineColor.colorToDoubleSequence(mxCanvas->getDevice());
[ # # ][ # # ]
[ # # ]
565 [ # # ][ # # ]: 0 : canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
566 : :
567 [ # # ]: 0 : mxCanvas->strokePolyPolygon(
568 [ # # ]: 0 : basegfx::unotools::xPolyPolygonFromB2DPolygon(mxCanvas->getDevice(), rPolygonStrokePrimitive.getB2DPolygon()),
569 [ # # ][ # # ]: 0 : maViewState, maRenderState, aStrokeAttribute);
[ # # ]
570 : :
571 [ # # ]: 0 : bOutputDone = true;
572 : : }
573 : : }
574 : :
575 [ # # ]: 0 : if(!bOutputDone)
576 : : {
577 : : // process decomposition
578 [ # # ]: 0 : process(rPolygonStrokePrimitive.get2DDecomposition(getViewInformation2D()));
579 : : }
580 : 0 : }
581 : :
582 : 0 : void canvasProcessor2D::impRenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapPrimitive2D)
583 : : {
584 : : // support tiled fills directly when tiling is on
585 : : static bool bSupportFillBitmapDirectly(true);
586 : 0 : bool bOutputDone(false);
587 : :
588 [ # # ]: 0 : if(bSupportFillBitmapDirectly)
589 : : {
590 : 0 : const attribute::FillBitmapAttribute& rFillBitmapAttribute = rFillBitmapPrimitive2D.getFillBitmap();
591 : :
592 [ # # ]: 0 : if(rFillBitmapAttribute.getTiling())
593 : : {
594 : : // apply possible color modification to Bitmap
595 [ # # ][ # # ]: 0 : const BitmapEx aChangedBitmapEx(impModifyBitmapEx(maBColorModifierStack, rFillBitmapAttribute.getBitmapEx()));
596 : :
597 [ # # ][ # # ]: 0 : if(aChangedBitmapEx.IsEmpty())
598 : : {
599 : : // replace with color filled polygon
600 [ # # ]: 0 : const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
601 [ # # ]: 0 : const basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon());
602 : :
603 [ # # ][ # # ]: 0 : maRenderState.DeviceColor = aModifiedColor.colorToDoubleSequence(mxCanvas->getDevice());
[ # # ][ # # ]
[ # # ]
604 : : canvas::tools::setRenderStateTransform(maRenderState,
605 [ # # ][ # # ]: 0 : getViewInformation2D().getObjectTransformation() * rFillBitmapPrimitive2D.getTransformation());
[ # # ][ # # ]
606 : :
607 [ # # ]: 0 : mxCanvas->fillPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
608 [ # # ][ # # ]: 0 : mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aPolygon)), maViewState, maRenderState);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
609 : : }
610 : : else
611 : : {
612 : 0 : const Size aSizePixel(aChangedBitmapEx.GetSizePixel());
613 : :
614 [ # # ][ # # ]: 0 : if(0 != aSizePixel.Width() && 0 != aSizePixel.Height())
[ # # ]
615 : : {
616 : : // create texture matrix from texture to object (where object is unit square here),
617 : : // so use values directly
618 : : const basegfx::B2DHomMatrix aTextureMatrix(basegfx::tools::createScaleTranslateB2DHomMatrix(
619 [ # # # # ]: 0 : rFillBitmapAttribute.getSize().getX(), rFillBitmapAttribute.getSize().getY(),
620 [ # # ][ # # ]: 0 : rFillBitmapAttribute.getTopLeft().getX(), rFillBitmapAttribute.getTopLeft().getY()));
[ # # ]
621 : :
622 : : // create and fill texture
623 [ # # ]: 0 : rendering::Texture aTexture;
624 : :
625 [ # # ]: 0 : basegfx::unotools::affineMatrixFromHomMatrix(aTexture.AffineTransform, aTextureMatrix);
626 : 0 : aTexture.Alpha = 1.0;
627 [ # # ][ # # ]: 0 : aTexture.Bitmap = vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(), aChangedBitmapEx);
[ # # ][ # # ]
628 : 0 : aTexture.RepeatModeX = rendering::TexturingMode::REPEAT;
629 : 0 : aTexture.RepeatModeY = rendering::TexturingMode::REPEAT;
630 : :
631 : : // canvas needs a polygon to fill, create unit rectangle polygon
632 [ # # ]: 0 : const basegfx::B2DPolygon aOutlineRectangle(basegfx::tools::createUnitPolygon());
633 : :
634 : : // set primitive's transformation as render state transform
635 : : canvas::tools::setRenderStateTransform(maRenderState,
636 [ # # ][ # # ]: 0 : getViewInformation2D().getObjectTransformation() * rFillBitmapPrimitive2D.getTransformation());
[ # # ][ # # ]
637 : :
638 : : // put texture into a uno sequence for handover
639 [ # # ]: 0 : uno::Sequence< rendering::Texture > aSeq(1);
640 [ # # ][ # # ]: 0 : aSeq[0] = aTexture;
641 : :
642 : : // draw textured rectangle
643 [ # # ]: 0 : mxCanvas->fillTexturedPolyPolygon(
644 [ # # ]: 0 : basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aOutlineRectangle)),
645 [ # # ][ # # ]: 0 : maViewState, maRenderState, aSeq);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
646 : : }
647 : : }
648 : :
649 [ # # ]: 0 : bOutputDone = true;
650 : : }
651 : : }
652 : :
653 [ # # ]: 0 : if(!bOutputDone)
654 : : {
655 : : // process decomposition
656 [ # # ]: 0 : process(rFillBitmapPrimitive2D.get2DDecomposition(getViewInformation2D()));
657 : : }
658 : 0 : }
659 : :
660 : 0 : void canvasProcessor2D::impRenderUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate)
661 : : {
662 [ # # ]: 0 : if(0.0 == rUniTransparenceCandidate.getTransparence())
663 : : {
664 : : // not transparent at all, directly use content
665 : 0 : process(rUniTransparenceCandidate.getChildren());
666 : : }
667 [ # # ][ # # ]: 0 : else if(rUniTransparenceCandidate.getTransparence() > 0.0 && rUniTransparenceCandidate.getTransparence() < 1.0)
[ # # ]
668 : : {
669 [ # # ]: 0 : const primitive2d::Primitive2DSequence rChildren = rUniTransparenceCandidate.getChildren();
670 : :
671 [ # # ]: 0 : if(rChildren.hasElements())
672 : : {
673 : 0 : bool bOutputDone(false);
674 : :
675 : : // Detect if a single PolyPolygonColorPrimitive2D is contained; in that case,
676 : : // use the fillPolyPolygon method with correctly set transparence. This is a often used
677 : : // case, so detectiong it is valuable
678 [ # # ]: 0 : if(1 == rChildren.getLength())
679 : : {
680 : 0 : const primitive2d::Primitive2DReference xReference(rChildren[0]);
681 [ # # ][ # # ]: 0 : const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get());
682 : :
683 [ # # ][ # # ]: 0 : if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID())
[ # # ][ # # ]
684 : : {
685 : : // direct draw of PolyPolygon with color and transparence
686 [ # # ]: 0 : const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
687 : :
688 : : // add transparence modulation value to DeviceColor
689 [ # # ]: 0 : uno::Sequence< double > aColor(4);
690 : :
691 [ # # ]: 0 : aColor[0] = aPolygonColor.getRed();
692 [ # # ]: 0 : aColor[1] = aPolygonColor.getGreen();
693 [ # # ]: 0 : aColor[2] = aPolygonColor.getBlue();
694 [ # # ]: 0 : aColor[3] = 1.0 - rUniTransparenceCandidate.getTransparence();
695 [ # # ]: 0 : maRenderState.DeviceColor = aColor;
696 : :
697 [ # # ][ # # ]: 0 : canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
698 [ # # ]: 0 : mxCanvas->fillPolyPolygon(
699 [ # # ]: 0 : basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), pPoPoColor->getB2DPolyPolygon()),
700 [ # # ][ # # ]: 0 : maViewState, maRenderState);
[ # # ]
701 [ # # ]: 0 : bOutputDone = true;
702 : 0 : }
703 : : }
704 : :
705 [ # # ]: 0 : if(!bOutputDone)
706 : : {
707 : : // process decomposition. This will be decomposed to an TransparencePrimitive2D
708 : : // with the same child context and a single polygon for transparent context. This could be
709 : : // directly handled here with known VCL-buffer technology, but would only
710 : : // make a small difference compared to directly rendering the TransparencePrimitive2D
711 : : // using impRenderTransparencePrimitive2D above.
712 [ # # ][ # # ]: 0 : process(rUniTransparenceCandidate.get2DDecomposition(getViewInformation2D()));
[ # # ]
713 : : }
714 [ # # ]: 0 : }
715 : : }
716 : 0 : }
717 : :
718 : : //////////////////////////////////////////////////////////////////////////////
719 : : // internal processing support
720 : :
721 : 0 : void canvasProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
722 : : {
723 [ # # # # : 0 : switch(rCandidate.getPrimitive2DID())
# # # # #
# # # # #
# # # ]
724 : : {
725 : : case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
726 : : {
727 : : // direct draw of hairline
728 : 0 : const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate);
729 [ # # ]: 0 : const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
730 : :
731 [ # # ][ # # ]: 0 : maRenderState.DeviceColor = aHairlineColor.colorToDoubleSequence(mxCanvas->getDevice());
[ # # ][ # # ]
[ # # ]
732 [ # # ][ # # ]: 0 : canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
733 [ # # ]: 0 : mxCanvas->drawPolyPolygon(
734 [ # # ]: 0 : basegfx::unotools::xPolyPolygonFromB2DPolygon(mxCanvas->getDevice(), rPolygonCandidate.getB2DPolygon()),
735 [ # # ][ # # ]: 0 : maViewState, maRenderState);
[ # # ]
736 : :
737 : 0 : break;
738 : : }
739 : : case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
740 : : {
741 : : // direct draw of PolyPolygon with color
742 : 0 : const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate = static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate);
743 [ # # ]: 0 : const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
744 : :
745 [ # # ][ # # ]: 0 : maRenderState.DeviceColor = aPolygonColor.colorToDoubleSequence(mxCanvas->getDevice());
[ # # ][ # # ]
[ # # ]
746 [ # # ][ # # ]: 0 : canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
747 [ # # ]: 0 : mxCanvas->fillPolyPolygon(
748 [ # # ]: 0 : basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), rPolygonCandidate.getB2DPolyPolygon()),
749 [ # # ][ # # ]: 0 : maViewState, maRenderState);
[ # # ]
750 : :
751 : 0 : break;
752 : : }
753 : : case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
754 : : {
755 : : // modified color group. Force output to unified color.
756 : 0 : const primitive2d::ModifiedColorPrimitive2D& rModifiedCandidate = static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate);
757 : :
758 [ # # ]: 0 : if(rModifiedCandidate.getChildren().hasElements())
759 : : {
760 : 0 : maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
761 : 0 : process(rModifiedCandidate.getChildren());
762 : 0 : maBColorModifierStack.pop();
763 : : }
764 : :
765 : 0 : break;
766 : : }
767 : : case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
768 : : {
769 : : // mask group
770 : 0 : impRenderMaskPrimitive2D(static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate));
771 : :
772 : 0 : break;
773 : : }
774 : : case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
775 : : {
776 : : // transform group. Remember current ViewInformation2D
777 : 0 : const primitive2d::TransformPrimitive2D& rTransformCandidate = static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate);
778 [ # # ]: 0 : const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
779 : :
780 : : // create new local ViewInformation2D with new transformation
781 : : const geometry::ViewInformation2D aViewInformation2D(
782 [ # # ]: 0 : getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
783 [ # # ]: 0 : getViewInformation2D().getViewTransformation(),
784 [ # # ]: 0 : getViewInformation2D().getViewport(),
785 [ # # ]: 0 : getViewInformation2D().getVisualizedPage(),
786 : 0 : getViewInformation2D().getViewTime(),
787 [ # # # # ]: 0 : getViewInformation2D().getExtendedInformationSequence());
[ # # ][ # # ]
[ # # ]
788 [ # # ]: 0 : updateViewInformation(aViewInformation2D);
789 : :
790 : : // set at canvas
791 [ # # ][ # # ]: 0 : canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
792 : :
793 : : // proccess content
794 [ # # ]: 0 : process(rTransformCandidate.getChildren());
795 : :
796 : : // restore transformations
797 [ # # ]: 0 : updateViewInformation(aLastViewInformation2D);
798 : :
799 : : // restore at canvas
800 [ # # ][ # # ]: 0 : canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
801 : :
802 [ # # ][ # # ]: 0 : break;
803 : : }
804 : : case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
805 : : {
806 : : // new XDrawPage for ViewInformation2D
807 : 0 : const primitive2d::PagePreviewPrimitive2D& rPagePreviewCandidate = static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate);
808 : :
809 : : // remember current transformation and ViewInformation
810 [ # # ]: 0 : const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
811 : :
812 : : // create new local ViewInformation2D
813 : : const geometry::ViewInformation2D aViewInformation2D(
814 [ # # ]: 0 : getViewInformation2D().getObjectTransformation(),
815 [ # # ]: 0 : getViewInformation2D().getViewTransformation(),
816 [ # # ]: 0 : getViewInformation2D().getViewport(),
817 : 0 : rPagePreviewCandidate.getXDrawPage(),
818 : 0 : getViewInformation2D().getViewTime(),
819 [ # # # # ]: 0 : getViewInformation2D().getExtendedInformationSequence());
[ # # ]
820 [ # # ]: 0 : updateViewInformation(aViewInformation2D);
821 : :
822 : : // proccess decomposed content
823 [ # # ][ # # ]: 0 : process(rPagePreviewCandidate.get2DDecomposition(getViewInformation2D()));
[ # # ]
824 : :
825 : : // restore transformations
826 [ # # ]: 0 : updateViewInformation(aLastViewInformation2D);
827 [ # # ][ # # ]: 0 : break;
828 : : }
829 : : case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
830 : : {
831 : : // MetaFile primitive
832 : 0 : impRenderMetafilePrimitive2D(static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate));
833 : :
834 : 0 : break;
835 : : }
836 : : case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
837 : : {
838 : : // PointArray primitive
839 : 0 : const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate = static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate);
840 : :
841 : : // set point color
842 [ # # ]: 0 : const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rPointArrayCandidate.getRGBColor()));
843 [ # # ][ # # ]: 0 : maRenderState.DeviceColor = aRGBColor.colorToDoubleSequence(mxCanvas->getDevice());
[ # # ][ # # ]
[ # # ]
844 [ # # ][ # # ]: 0 : canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
845 : :
846 : 0 : const std::vector< basegfx::B2DPoint >& rPointVector = rPointArrayCandidate.getPositions();
847 : 0 : const sal_uInt32 nPointCount(rPointVector.size());
848 : :
849 [ # # ]: 0 : for(sal_uInt32 a(0); a < nPointCount; a++)
850 : : {
851 : 0 : const basegfx::B2DPoint& rPoint = rPointVector[a];
852 [ # # ][ # # ]: 0 : mxCanvas->drawPoint(basegfx::unotools::point2DFromB2DPoint(rPoint), maViewState, maRenderState);
[ # # ]
853 : : }
854 : :
855 : 0 : break;
856 : : }
857 : : case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
858 : : {
859 : : // TextSimplePortion primitive
860 : 0 : impRenderTextSimplePortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate));
861 : :
862 : 0 : break;
863 : : }
864 : : case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
865 : : {
866 : : // Bitmap primitive
867 : 0 : impRenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
868 : :
869 : 0 : break;
870 : : }
871 : : case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D :
872 : : {
873 : : // Transparence primitive
874 : 0 : impRenderTransparencePrimitive2D(static_cast< const primitive2d::TransparencePrimitive2D& >(rCandidate));
875 : :
876 : 0 : break;
877 : : }
878 : : case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
879 : : {
880 : : // PolygonStrokePrimitive
881 : 0 : impRenderPolygonStrokePrimitive2D(static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate));
882 : :
883 : 0 : break;
884 : : }
885 : : case PRIMITIVE2D_ID_FILLBITMAPPRIMITIVE2D :
886 : : {
887 : : // FillBitmapPrimitive2D
888 : 0 : impRenderFillBitmapPrimitive2D(static_cast< const primitive2d::FillBitmapPrimitive2D& >(rCandidate));
889 : :
890 : 0 : break;
891 : : }
892 : : case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D :
893 : : {
894 : : // UnifiedTransparencePrimitive2D
895 : 0 : impRenderUnifiedTransparencePrimitive2D(static_cast< const primitive2d::UnifiedTransparencePrimitive2D& >(rCandidate));
896 : :
897 : 0 : break;
898 : : }
899 : : case PRIMITIVE2D_ID_CHARTPRIMITIVE2D :
900 : : {
901 : : // chart primitive in canvas renderer; restore original DrawMode during call
902 : : // since the evtl. used ChartPrettyPainter will use the MapMode
903 : 0 : const primitive2d::ChartPrimitive2D& rChartPrimitive = static_cast< const primitive2d::ChartPrimitive2D& >(rCandidate);
904 : 0 : mpOutputDevice->Push(PUSH_MAPMODE);
905 : 0 : mpOutputDevice->SetMapMode(maOriginalMapMode);
906 : :
907 [ # # ]: 0 : if(!renderChartPrimitive2D(
908 : : rChartPrimitive,
909 : : *mpOutputDevice,
910 : 0 : getViewInformation2D()))
911 : : {
912 : : // fallback to decomposition (MetaFile)
913 [ # # ]: 0 : process(rChartPrimitive.get2DDecomposition(getViewInformation2D()));
914 : : }
915 : :
916 : 0 : mpOutputDevice->Pop();
917 : 0 : break;
918 : : }
919 : : case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
920 : : {
921 : : // wrong spell primitive. Handled directly here using VCL since VCL has a nice and
922 : : // very direct waveline painting which is needed for this. If VCL is to be avoided,
923 : : // this can be removed anytime and the decomposition may be used
924 : 0 : const primitive2d::WrongSpellPrimitive2D& rWrongSpellPrimitive = static_cast< const primitive2d::WrongSpellPrimitive2D& >(rCandidate);
925 : :
926 [ # # ]: 0 : if(!renderWrongSpellPrimitive2D(
927 : : rWrongSpellPrimitive,
928 : : *mpOutputDevice,
929 : 0 : getViewInformation2D().getObjectToViewTransformation(),
930 : 0 : maBColorModifierStack))
931 : : {
932 : : // fallback to decomposition (MetaFile)
933 [ # # ]: 0 : process(rWrongSpellPrimitive.get2DDecomposition(getViewInformation2D()));
934 : : }
935 : :
936 : 0 : break;
937 : : }
938 : :
939 : : // nice to have:
940 : : //
941 : : // case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
942 : : // - support FormControls more direct eventually, not sure if this is needed
943 : : // with the canvas renderer. The decomposition provides a bitmap representation
944 : : // of the control which will work
945 : : //
946 : :
947 : : default :
948 : : {
949 : : // process recursively
950 [ # # ]: 0 : process(rCandidate.get2DDecomposition(getViewInformation2D()));
951 : :
952 : 0 : break;
953 : : }
954 : : }
955 : 0 : }
956 : :
957 : : //////////////////////////////////////////////////////////////////////////////
958 : : // process support
959 : :
960 : 0 : canvasProcessor2D::canvasProcessor2D(
961 : : const geometry::ViewInformation2D& rViewInformation,
962 : : OutputDevice& rOutDev)
963 : : : BaseProcessor2D(rViewInformation),
964 : 0 : maOriginalMapMode(rOutDev.GetMapMode()),
965 : : mpOutputDevice(&rOutDev),
966 : : mxCanvas(rOutDev.GetCanvas()),
967 : : maViewState(),
968 : : maRenderState(),
969 : : maBColorModifierStack(),
970 : : maDrawinglayerOpt(),
971 : : maClipPolyPolygon(),
972 [ # # ][ # # ]: 0 : meLang(drawinglayer::detail::getDigitLanguage())
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
973 : : {
974 [ # # ]: 0 : canvas::tools::initViewState(maViewState);
975 [ # # ]: 0 : canvas::tools::initRenderState(maRenderState);
976 [ # # ][ # # ]: 0 : canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
977 : :
978 : : // set digit language, derived from SvtCTLOptions to have the correct
979 : : // number display for arabic/hindi numerals
980 [ # # ]: 0 : rOutDev.SetDigitLanguage(meLang);
981 : :
982 : : // prepare output directly to pixels
983 [ # # ]: 0 : mpOutputDevice->Push(PUSH_MAPMODE);
984 [ # # ]: 0 : mpOutputDevice->SetMapMode();
985 : :
986 : : // react on AntiAliasing settings
987 [ # # ][ # # ]: 0 : if(getOptionsDrawinglayer().IsAntiAliasing())
988 : : {
989 [ # # ]: 0 : mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW);
990 : : }
991 : : else
992 : : {
993 [ # # ]: 0 : mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW);
994 : : }
995 : 0 : }
996 : :
997 [ # # ][ # # ]: 0 : canvasProcessor2D::~canvasProcessor2D()
[ # # ][ # # ]
[ # # ]
998 : : {
999 : : // restore MapMode
1000 [ # # ]: 0 : mpOutputDevice->Pop();
1001 : :
1002 : : // restore AntiAliasing
1003 [ # # ]: 0 : mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW);
1004 [ # # ]: 0 : }
1005 : : } // end of namespace processor2d
1006 : : } // end of namespace drawinglayer
1007 : :
1008 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|