1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_slideshow.hxx"
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski // must be first
28*b1cdbd2cSJim Jagielski #include <canvas/debug.hxx>
29*b1cdbd2cSJim Jagielski #include <tools/diagnose_ex.h>
30*b1cdbd2cSJim Jagielski 
31*b1cdbd2cSJim Jagielski #include <math.h>
32*b1cdbd2cSJim Jagielski 
33*b1cdbd2cSJim Jagielski #include <rtl/logfile.hxx>
34*b1cdbd2cSJim Jagielski #include <rtl/math.hxx>
35*b1cdbd2cSJim Jagielski 
36*b1cdbd2cSJim Jagielski #include <com/sun/star/rendering/XCanvas.hpp>
37*b1cdbd2cSJim Jagielski #include <com/sun/star/rendering/XIntegerBitmap.hpp>
38*b1cdbd2cSJim Jagielski #include <com/sun/star/rendering/PanoseLetterForm.hpp>
39*b1cdbd2cSJim Jagielski #include <com/sun/star/awt/FontSlant.hpp>
40*b1cdbd2cSJim Jagielski 
41*b1cdbd2cSJim Jagielski #include <cppuhelper/exc_hlp.hxx>
42*b1cdbd2cSJim Jagielski #include <comphelper/anytostring.hxx>
43*b1cdbd2cSJim Jagielski 
44*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolygontools.hxx>
45*b1cdbd2cSJim Jagielski #include <basegfx/numeric/ftools.hxx>
46*b1cdbd2cSJim Jagielski #include <basegfx/matrix/b2dhommatrix.hxx>
47*b1cdbd2cSJim Jagielski #include <basegfx/matrix/b2dhommatrixtools.hxx>
48*b1cdbd2cSJim Jagielski 
49*b1cdbd2cSJim Jagielski #include <canvas/verbosetrace.hxx>
50*b1cdbd2cSJim Jagielski #include <canvas/canvastools.hxx>
51*b1cdbd2cSJim Jagielski #include <cppcanvas/vclfactory.hxx>
52*b1cdbd2cSJim Jagielski #include <cppcanvas/basegfxfactory.hxx>
53*b1cdbd2cSJim Jagielski 
54*b1cdbd2cSJim Jagielski #include "viewshape.hxx"
55*b1cdbd2cSJim Jagielski #include "tools.hxx"
56*b1cdbd2cSJim Jagielski 
57*b1cdbd2cSJim Jagielski #include <boost/bind.hpp>
58*b1cdbd2cSJim Jagielski 
59*b1cdbd2cSJim Jagielski 
60*b1cdbd2cSJim Jagielski using namespace ::com::sun::star;
61*b1cdbd2cSJim Jagielski 
62*b1cdbd2cSJim Jagielski namespace slideshow
63*b1cdbd2cSJim Jagielski {
64*b1cdbd2cSJim Jagielski     namespace internal
65*b1cdbd2cSJim Jagielski     {
66*b1cdbd2cSJim Jagielski 
67*b1cdbd2cSJim Jagielski         // TODO(F2): Provide sensible setup for mtf-related attributes (fill mode,
68*b1cdbd2cSJim Jagielski         // char rotation etc.). Do that via mtf argument at this object
69*b1cdbd2cSJim Jagielski 
prefetch(RendererCacheEntry & io_rCacheEntry,const::cppcanvas::CanvasSharedPtr & rDestinationCanvas,const GDIMetaFileSharedPtr & rMtf,const ShapeAttributeLayerSharedPtr & rAttr) const70*b1cdbd2cSJim Jagielski         bool ViewShape::prefetch( RendererCacheEntry&					io_rCacheEntry,
71*b1cdbd2cSJim Jagielski                                   const ::cppcanvas::CanvasSharedPtr&	rDestinationCanvas,
72*b1cdbd2cSJim Jagielski                                   const GDIMetaFileSharedPtr&			rMtf,
73*b1cdbd2cSJim Jagielski                                   const ShapeAttributeLayerSharedPtr&	rAttr ) const
74*b1cdbd2cSJim Jagielski         {
75*b1cdbd2cSJim Jagielski             RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::ViewShape::prefetch()" );
76*b1cdbd2cSJim Jagielski             ENSURE_OR_RETURN_FALSE( rMtf,
77*b1cdbd2cSJim Jagielski                                "ViewShape::prefetch(): no valid metafile!" );
78*b1cdbd2cSJim Jagielski 
79*b1cdbd2cSJim Jagielski             if( rMtf != io_rCacheEntry.mpMtf ||
80*b1cdbd2cSJim Jagielski                 rDestinationCanvas != io_rCacheEntry.getDestinationCanvas() )
81*b1cdbd2cSJim Jagielski             {
82*b1cdbd2cSJim Jagielski                 // buffered renderer invalid, re-create
83*b1cdbd2cSJim Jagielski                 ::cppcanvas::Renderer::Parameters aParms;
84*b1cdbd2cSJim Jagielski 
85*b1cdbd2cSJim Jagielski                 // rendering attribute override parameter struct.  For
86*b1cdbd2cSJim Jagielski                 // every valid attribute, the corresponding struct
87*b1cdbd2cSJim Jagielski                 // member is filled, which in the metafile renderer
88*b1cdbd2cSJim Jagielski                 // forces rendering with the given attribute.
89*b1cdbd2cSJim Jagielski                 if( rAttr )
90*b1cdbd2cSJim Jagielski                 {
91*b1cdbd2cSJim Jagielski                     if( rAttr->isFillColorValid() )
92*b1cdbd2cSJim Jagielski                     {
93*b1cdbd2cSJim Jagielski                         // convert RGBColor to RGBA32 integer. Note
94*b1cdbd2cSJim Jagielski                         // that getIntegerColor() also truncates
95*b1cdbd2cSJim Jagielski                         // out-of-range values appropriately
96*b1cdbd2cSJim Jagielski                         aParms.maFillColor =
97*b1cdbd2cSJim Jagielski                             rAttr->getFillColor().getIntegerColor();
98*b1cdbd2cSJim Jagielski                     }
99*b1cdbd2cSJim Jagielski                     if( rAttr->isLineColorValid() )
100*b1cdbd2cSJim Jagielski                     {
101*b1cdbd2cSJim Jagielski                         // convert RGBColor to RGBA32 integer. Note
102*b1cdbd2cSJim Jagielski                         // that getIntegerColor() also truncates
103*b1cdbd2cSJim Jagielski                         // out-of-range values appropriately
104*b1cdbd2cSJim Jagielski                         aParms.maLineColor =
105*b1cdbd2cSJim Jagielski                             rAttr->getLineColor().getIntegerColor();
106*b1cdbd2cSJim Jagielski                     }
107*b1cdbd2cSJim Jagielski                     if( rAttr->isCharColorValid() )
108*b1cdbd2cSJim Jagielski                     {
109*b1cdbd2cSJim Jagielski                         // convert RGBColor to RGBA32 integer. Note
110*b1cdbd2cSJim Jagielski                         // that getIntegerColor() also truncates
111*b1cdbd2cSJim Jagielski                         // out-of-range values appropriately
112*b1cdbd2cSJim Jagielski                         aParms.maTextColor =
113*b1cdbd2cSJim Jagielski                             rAttr->getCharColor().getIntegerColor();
114*b1cdbd2cSJim Jagielski                     }
115*b1cdbd2cSJim Jagielski                     if( rAttr->isDimColorValid() )
116*b1cdbd2cSJim Jagielski                     {
117*b1cdbd2cSJim Jagielski                         // convert RGBColor to RGBA32 integer. Note
118*b1cdbd2cSJim Jagielski                         // that getIntegerColor() also truncates
119*b1cdbd2cSJim Jagielski                         // out-of-range values appropriately
120*b1cdbd2cSJim Jagielski 
121*b1cdbd2cSJim Jagielski                         // dim color overrides all other colors
122*b1cdbd2cSJim Jagielski                         aParms.maFillColor =
123*b1cdbd2cSJim Jagielski                         aParms.maLineColor =
124*b1cdbd2cSJim Jagielski                         aParms.maTextColor =
125*b1cdbd2cSJim Jagielski                             rAttr->getDimColor().getIntegerColor();
126*b1cdbd2cSJim Jagielski                     }
127*b1cdbd2cSJim Jagielski                     if( rAttr->isFontFamilyValid() )
128*b1cdbd2cSJim Jagielski                     {
129*b1cdbd2cSJim Jagielski                         aParms.maFontName =
130*b1cdbd2cSJim Jagielski                             rAttr->getFontFamily();
131*b1cdbd2cSJim Jagielski                     }
132*b1cdbd2cSJim Jagielski                     if( rAttr->isCharScaleValid() )
133*b1cdbd2cSJim Jagielski                     {
134*b1cdbd2cSJim Jagielski                         ::basegfx::B2DHomMatrix aMatrix;
135*b1cdbd2cSJim Jagielski 
136*b1cdbd2cSJim Jagielski                         // enlarge text by given scale factor. Do that
137*b1cdbd2cSJim Jagielski                         // with the middle of the shape as the center
138*b1cdbd2cSJim Jagielski                         // of scaling.
139*b1cdbd2cSJim Jagielski                         aMatrix.translate( -0.5, -0.5 );
140*b1cdbd2cSJim Jagielski                         aMatrix.scale( rAttr->getCharScale(),
141*b1cdbd2cSJim Jagielski                                        rAttr->getCharScale() );
142*b1cdbd2cSJim Jagielski                         aMatrix.translate( 0.5, 0.5 );
143*b1cdbd2cSJim Jagielski 
144*b1cdbd2cSJim Jagielski                         aParms.maTextTransformation = aMatrix;
145*b1cdbd2cSJim Jagielski                     }
146*b1cdbd2cSJim Jagielski                     if( rAttr->isCharWeightValid() )
147*b1cdbd2cSJim Jagielski                     {
148*b1cdbd2cSJim Jagielski                         aParms.maFontWeight =
149*b1cdbd2cSJim Jagielski                             static_cast< sal_Int8 >(
150*b1cdbd2cSJim Jagielski                                 ::basegfx::fround(
151*b1cdbd2cSJim Jagielski                                     ::std::max( 0.0,
152*b1cdbd2cSJim Jagielski                                                 ::std::min( 11.0,
153*b1cdbd2cSJim Jagielski                                                             rAttr->getCharWeight() / 20.0 ) ) ) );
154*b1cdbd2cSJim Jagielski                     }
155*b1cdbd2cSJim Jagielski                     if( rAttr->isCharPostureValid() )
156*b1cdbd2cSJim Jagielski                     {
157*b1cdbd2cSJim Jagielski                         aParms.maFontLetterForm =
158*b1cdbd2cSJim Jagielski                             rAttr->getCharPosture() == awt::FontSlant_NONE ?
159*b1cdbd2cSJim Jagielski                             rendering::PanoseLetterForm::ANYTHING :
160*b1cdbd2cSJim Jagielski                             rendering::PanoseLetterForm::OBLIQUE_CONTACT;
161*b1cdbd2cSJim Jagielski                     }
162*b1cdbd2cSJim Jagielski                     if( rAttr->isUnderlineModeValid() )
163*b1cdbd2cSJim Jagielski                     {
164*b1cdbd2cSJim Jagielski                         aParms.maFontUnderline =
165*b1cdbd2cSJim Jagielski                             rAttr->getUnderlineMode();
166*b1cdbd2cSJim Jagielski                     }
167*b1cdbd2cSJim Jagielski                 }
168*b1cdbd2cSJim Jagielski 
169*b1cdbd2cSJim Jagielski                 io_rCacheEntry.mpRenderer = ::cppcanvas::VCLFactory::getInstance().createRenderer( rDestinationCanvas,
170*b1cdbd2cSJim Jagielski                                                                                                    *rMtf.get(),
171*b1cdbd2cSJim Jagielski                                                                                                    aParms );
172*b1cdbd2cSJim Jagielski 
173*b1cdbd2cSJim Jagielski                 io_rCacheEntry.mpMtf      		   = rMtf;
174*b1cdbd2cSJim Jagielski                 io_rCacheEntry.mpDestinationCanvas = rDestinationCanvas;
175*b1cdbd2cSJim Jagielski 
176*b1cdbd2cSJim Jagielski                 // also invalidate alpha compositing bitmap (created
177*b1cdbd2cSJim Jagielski                 // new renderer, which possibly generates different
178*b1cdbd2cSJim Jagielski                 // output). Do NOT invalidate, if we're incidentally
179*b1cdbd2cSJim Jagielski                 // rendering INTO it.
180*b1cdbd2cSJim Jagielski                 if( rDestinationCanvas != io_rCacheEntry.mpLastBitmapCanvas )
181*b1cdbd2cSJim Jagielski                 {
182*b1cdbd2cSJim Jagielski                     io_rCacheEntry.mpLastBitmapCanvas.reset();
183*b1cdbd2cSJim Jagielski                     io_rCacheEntry.mpLastBitmap.reset();
184*b1cdbd2cSJim Jagielski                 }
185*b1cdbd2cSJim Jagielski             }
186*b1cdbd2cSJim Jagielski 
187*b1cdbd2cSJim Jagielski             return (io_rCacheEntry.mpRenderer.get() != NULL);
188*b1cdbd2cSJim Jagielski         }
189*b1cdbd2cSJim Jagielski 
draw(const::cppcanvas::CanvasSharedPtr & rDestinationCanvas,const GDIMetaFileSharedPtr & rMtf,const ShapeAttributeLayerSharedPtr & rAttr,const::basegfx::B2DHomMatrix & rTransform,const::basegfx::B2DPolyPolygon * pClip,const VectorOfDocTreeNodes & rSubsets) const190*b1cdbd2cSJim Jagielski         bool ViewShape::draw( const ::cppcanvas::CanvasSharedPtr&	rDestinationCanvas,
191*b1cdbd2cSJim Jagielski                               const GDIMetaFileSharedPtr&			rMtf,
192*b1cdbd2cSJim Jagielski                               const ShapeAttributeLayerSharedPtr&	rAttr,
193*b1cdbd2cSJim Jagielski                               const ::basegfx::B2DHomMatrix&		rTransform,
194*b1cdbd2cSJim Jagielski                               const ::basegfx::B2DPolyPolygon*		pClip,
195*b1cdbd2cSJim Jagielski                               const VectorOfDocTreeNodes&			rSubsets ) const
196*b1cdbd2cSJim Jagielski         {
197*b1cdbd2cSJim Jagielski             RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::ViewShape::draw()" );
198*b1cdbd2cSJim Jagielski 
199*b1cdbd2cSJim Jagielski             ::cppcanvas::RendererSharedPtr pRenderer(
200*b1cdbd2cSJim Jagielski                 getRenderer( rDestinationCanvas, rMtf, rAttr ) );
201*b1cdbd2cSJim Jagielski 
202*b1cdbd2cSJim Jagielski             ENSURE_OR_RETURN_FALSE( pRenderer, "ViewShape::draw(): Invalid renderer" );
203*b1cdbd2cSJim Jagielski 
204*b1cdbd2cSJim Jagielski             pRenderer->setTransformation( rTransform );
205*b1cdbd2cSJim Jagielski #if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0
206*b1cdbd2cSJim Jagielski             rendering::RenderState aRenderState;
207*b1cdbd2cSJim Jagielski             ::canvas::tools::initRenderState(aRenderState);
208*b1cdbd2cSJim Jagielski             ::canvas::tools::setRenderStateTransform(aRenderState,
209*b1cdbd2cSJim Jagielski                                                      rTransform);
210*b1cdbd2cSJim Jagielski             aRenderState.DeviceColor.realloc(4);
211*b1cdbd2cSJim Jagielski             aRenderState.DeviceColor[0] = 1.0;
212*b1cdbd2cSJim Jagielski             aRenderState.DeviceColor[1] = 0.0;
213*b1cdbd2cSJim Jagielski             aRenderState.DeviceColor[2] = 0.0;
214*b1cdbd2cSJim Jagielski             aRenderState.DeviceColor[3] = 1.0;
215*b1cdbd2cSJim Jagielski 
216*b1cdbd2cSJim Jagielski             try
217*b1cdbd2cSJim Jagielski             {
218*b1cdbd2cSJim Jagielski                 rDestinationCanvas->getUNOCanvas()->drawLine( geometry::RealPoint2D(0.0,0.0),
219*b1cdbd2cSJim Jagielski                                                               geometry::RealPoint2D(1.0,1.0),
220*b1cdbd2cSJim Jagielski                                                               rDestinationCanvas->getViewState(),
221*b1cdbd2cSJim Jagielski                                                               aRenderState );
222*b1cdbd2cSJim Jagielski                 rDestinationCanvas->getUNOCanvas()->drawLine( geometry::RealPoint2D(1.0,0.0),
223*b1cdbd2cSJim Jagielski                                                               geometry::RealPoint2D(0.0,1.0),
224*b1cdbd2cSJim Jagielski                                                               rDestinationCanvas->getViewState(),
225*b1cdbd2cSJim Jagielski                                                               aRenderState );
226*b1cdbd2cSJim Jagielski             }
227*b1cdbd2cSJim Jagielski             catch( uno::Exception& )
228*b1cdbd2cSJim Jagielski             {
229*b1cdbd2cSJim Jagielski                 DBG_UNHANDLED_EXCEPTION();
230*b1cdbd2cSJim Jagielski             }
231*b1cdbd2cSJim Jagielski #endif
232*b1cdbd2cSJim Jagielski             if( pClip )
233*b1cdbd2cSJim Jagielski                 pRenderer->setClip( *pClip );
234*b1cdbd2cSJim Jagielski             else
235*b1cdbd2cSJim Jagielski                 pRenderer->setClip();
236*b1cdbd2cSJim Jagielski 
237*b1cdbd2cSJim Jagielski             if( rSubsets.empty() )
238*b1cdbd2cSJim Jagielski             {
239*b1cdbd2cSJim Jagielski                 return pRenderer->draw();
240*b1cdbd2cSJim Jagielski             }
241*b1cdbd2cSJim Jagielski             else
242*b1cdbd2cSJim Jagielski             {
243*b1cdbd2cSJim Jagielski                 // render subsets of whole metafile
244*b1cdbd2cSJim Jagielski                 // --------------------------------
245*b1cdbd2cSJim Jagielski 
246*b1cdbd2cSJim Jagielski                 bool bRet(true);
247*b1cdbd2cSJim Jagielski                 VectorOfDocTreeNodes::const_iterator 		aIter( rSubsets.begin() );
248*b1cdbd2cSJim Jagielski                 const VectorOfDocTreeNodes::const_iterator	aEnd ( rSubsets.end() );
249*b1cdbd2cSJim Jagielski                 while( aIter != aEnd )
250*b1cdbd2cSJim Jagielski                 {
251*b1cdbd2cSJim Jagielski                     if( !pRenderer->drawSubset( aIter->getStartIndex(),
252*b1cdbd2cSJim Jagielski                                                 aIter->getEndIndex() ) )
253*b1cdbd2cSJim Jagielski                         bRet = false;
254*b1cdbd2cSJim Jagielski 
255*b1cdbd2cSJim Jagielski                     ++aIter;
256*b1cdbd2cSJim Jagielski                 }
257*b1cdbd2cSJim Jagielski 
258*b1cdbd2cSJim Jagielski                 return bRet;
259*b1cdbd2cSJim Jagielski             }
260*b1cdbd2cSJim Jagielski         }
261*b1cdbd2cSJim Jagielski 
262*b1cdbd2cSJim Jagielski         namespace
263*b1cdbd2cSJim Jagielski         {
264*b1cdbd2cSJim Jagielski             /// Convert untransformed shape update area to device pixel.
shapeArea2AreaPixel(const::basegfx::B2DHomMatrix & rCanvasTransformation,const::basegfx::B2DRectangle & rUntransformedArea)265*b1cdbd2cSJim Jagielski             ::basegfx::B2DRectangle shapeArea2AreaPixel( const ::basegfx::B2DHomMatrix&	rCanvasTransformation,
266*b1cdbd2cSJim Jagielski                                                          const ::basegfx::B2DRectangle&	rUntransformedArea		)
267*b1cdbd2cSJim Jagielski             {
268*b1cdbd2cSJim Jagielski                 // convert area to pixel, and add anti-aliasing border
269*b1cdbd2cSJim Jagielski 
270*b1cdbd2cSJim Jagielski                 // TODO(P1): Should the view transform some
271*b1cdbd2cSJim Jagielski                 // day contain rotation/shear, transforming
272*b1cdbd2cSJim Jagielski                 // the original bounds with the total
273*b1cdbd2cSJim Jagielski                 // transformation might result in smaller
274*b1cdbd2cSJim Jagielski                 // overall bounds.
275*b1cdbd2cSJim Jagielski 
276*b1cdbd2cSJim Jagielski                 ::basegfx::B2DRectangle aBoundsPixel;
277*b1cdbd2cSJim Jagielski                 ::canvas::tools::calcTransformedRectBounds( aBoundsPixel,
278*b1cdbd2cSJim Jagielski                                                             rUntransformedArea,
279*b1cdbd2cSJim Jagielski                                                             rCanvasTransformation );
280*b1cdbd2cSJim Jagielski 
281*b1cdbd2cSJim Jagielski                 // add antialiasing border around the shape (AA
282*b1cdbd2cSJim Jagielski                 // touches pixel _outside_ the nominal bound rect)
283*b1cdbd2cSJim Jagielski                 aBoundsPixel.grow( ::cppcanvas::Canvas::ANTIALIASING_EXTRA_SIZE );
284*b1cdbd2cSJim Jagielski 
285*b1cdbd2cSJim Jagielski                 return aBoundsPixel;
286*b1cdbd2cSJim Jagielski             }
287*b1cdbd2cSJim Jagielski 
288*b1cdbd2cSJim Jagielski             /// Convert shape unit rect to device pixel.
calcUpdateAreaPixel(const::basegfx::B2DRectangle & rUnitBounds,const::basegfx::B2DHomMatrix & rShapeTransformation,const::basegfx::B2DHomMatrix & rCanvasTransformation,const ShapeAttributeLayerSharedPtr & pAttr)289*b1cdbd2cSJim Jagielski             ::basegfx::B2DRectangle calcUpdateAreaPixel( const ::basegfx::B2DRectangle& 		rUnitBounds,
290*b1cdbd2cSJim Jagielski                                                          const ::basegfx::B2DHomMatrix& 		rShapeTransformation,
291*b1cdbd2cSJim Jagielski                                                          const ::basegfx::B2DHomMatrix&			rCanvasTransformation,
292*b1cdbd2cSJim Jagielski                                                          const ShapeAttributeLayerSharedPtr&	pAttr					)
293*b1cdbd2cSJim Jagielski             {
294*b1cdbd2cSJim Jagielski                 // calc update area for whole shape (including
295*b1cdbd2cSJim Jagielski                 // character scaling)
296*b1cdbd2cSJim Jagielski                 return shapeArea2AreaPixel( rCanvasTransformation,
297*b1cdbd2cSJim Jagielski                                             getShapeUpdateArea( rUnitBounds,
298*b1cdbd2cSJim Jagielski                                                                 rShapeTransformation,
299*b1cdbd2cSJim Jagielski                                                                 pAttr ) );
300*b1cdbd2cSJim Jagielski             }
301*b1cdbd2cSJim Jagielski         }
302*b1cdbd2cSJim Jagielski 
renderSprite(const ViewLayerSharedPtr & rViewLayer,const GDIMetaFileSharedPtr & rMtf,const::basegfx::B2DRectangle & rOrigBounds,const::basegfx::B2DRectangle & rBounds,const::basegfx::B2DRectangle & rUnitBounds,int nUpdateFlags,const ShapeAttributeLayerSharedPtr & pAttr,const VectorOfDocTreeNodes & rSubsets,double nPrio,bool bIsVisible) const303*b1cdbd2cSJim Jagielski         bool ViewShape::renderSprite( const ViewLayerSharedPtr&             rViewLayer,
304*b1cdbd2cSJim Jagielski                                       const GDIMetaFileSharedPtr&			rMtf,
305*b1cdbd2cSJim Jagielski                                       const ::basegfx::B2DRectangle&		rOrigBounds,
306*b1cdbd2cSJim Jagielski                                       const ::basegfx::B2DRectangle&		rBounds,
307*b1cdbd2cSJim Jagielski                                       const ::basegfx::B2DRectangle&		rUnitBounds,
308*b1cdbd2cSJim Jagielski                                       int									nUpdateFlags,
309*b1cdbd2cSJim Jagielski                                       const ShapeAttributeLayerSharedPtr&	pAttr,
310*b1cdbd2cSJim Jagielski                                       const VectorOfDocTreeNodes&			rSubsets,
311*b1cdbd2cSJim Jagielski                                       double                                nPrio,
312*b1cdbd2cSJim Jagielski                                       bool 									bIsVisible ) const
313*b1cdbd2cSJim Jagielski         {
314*b1cdbd2cSJim Jagielski             RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::ViewShape::renderSprite()" );
315*b1cdbd2cSJim Jagielski 
316*b1cdbd2cSJim Jagielski             // TODO(P1): For multiple views, it might pay off to reorg Shape and ViewShape,
317*b1cdbd2cSJim Jagielski             // in that all the common setup steps here are refactored to Shape (would then
318*b1cdbd2cSJim Jagielski             // have to be performed only _once_ per Shape paint).
319*b1cdbd2cSJim Jagielski 
320*b1cdbd2cSJim Jagielski             if( !bIsVisible ||
321*b1cdbd2cSJim Jagielski                 rUnitBounds.isEmpty() ||
322*b1cdbd2cSJim Jagielski                 rOrigBounds.isEmpty() ||
323*b1cdbd2cSJim Jagielski                 rBounds.isEmpty() )
324*b1cdbd2cSJim Jagielski             {
325*b1cdbd2cSJim Jagielski                 // shape is invisible or has zero size, no need to
326*b1cdbd2cSJim Jagielski                 // update anything.
327*b1cdbd2cSJim Jagielski                 if( mpSprite )
328*b1cdbd2cSJim Jagielski                     mpSprite->hide();
329*b1cdbd2cSJim Jagielski 
330*b1cdbd2cSJim Jagielski                 return true;
331*b1cdbd2cSJim Jagielski             }
332*b1cdbd2cSJim Jagielski 
333*b1cdbd2cSJim Jagielski 
334*b1cdbd2cSJim Jagielski             // calc sprite position, size and content transformation
335*b1cdbd2cSJim Jagielski             // =====================================================
336*b1cdbd2cSJim Jagielski 
337*b1cdbd2cSJim Jagielski             // the shape transformation for a sprite is always a
338*b1cdbd2cSJim Jagielski             // simple scale-up to the nominal shape size. Everything
339*b1cdbd2cSJim Jagielski             // else is handled via the sprite transformation
340*b1cdbd2cSJim Jagielski             ::basegfx::B2DHomMatrix aNonTranslationalShapeTransformation;
341*b1cdbd2cSJim Jagielski             aNonTranslationalShapeTransformation.scale( rOrigBounds.getWidth(),
342*b1cdbd2cSJim Jagielski                                                         rOrigBounds.getHeight() );
343*b1cdbd2cSJim Jagielski             ::basegfx::B2DHomMatrix aShapeTransformation( aNonTranslationalShapeTransformation );
344*b1cdbd2cSJim Jagielski             aShapeTransformation.translate( rOrigBounds.getMinX(),
345*b1cdbd2cSJim Jagielski                                             rOrigBounds.getMinY() );
346*b1cdbd2cSJim Jagielski 
347*b1cdbd2cSJim Jagielski             const ::basegfx::B2DHomMatrix& rCanvasTransform(
348*b1cdbd2cSJim Jagielski                 rViewLayer->getSpriteTransformation() );
349*b1cdbd2cSJim Jagielski 
350*b1cdbd2cSJim Jagielski             // area actually needed for the sprite
351*b1cdbd2cSJim Jagielski             const ::basegfx::B2DRectangle& rSpriteBoundsPixel(
352*b1cdbd2cSJim Jagielski                 calcUpdateAreaPixel( rUnitBounds,
353*b1cdbd2cSJim Jagielski                                      aShapeTransformation,
354*b1cdbd2cSJim Jagielski                                      rCanvasTransform,
355*b1cdbd2cSJim Jagielski                                      pAttr ) );
356*b1cdbd2cSJim Jagielski 
357*b1cdbd2cSJim Jagielski             // actual area for the shape (without subsetting, but
358*b1cdbd2cSJim Jagielski             // including char scaling)
359*b1cdbd2cSJim Jagielski             const ::basegfx::B2DRectangle& rShapeBoundsPixel(
360*b1cdbd2cSJim Jagielski                 calcUpdateAreaPixel( ::basegfx::B2DRectangle(0.0,0.0,1.0,1.0),
361*b1cdbd2cSJim Jagielski                                      aShapeTransformation,
362*b1cdbd2cSJim Jagielski                                      rCanvasTransform,
363*b1cdbd2cSJim Jagielski                                      pAttr ) );
364*b1cdbd2cSJim Jagielski 
365*b1cdbd2cSJim Jagielski             // nominal area for the shape (without subsetting, without
366*b1cdbd2cSJim Jagielski             // char scaling). NOTE: to cancel the shape translation,
367*b1cdbd2cSJim Jagielski             // contained in rSpriteBoundsPixel, this is _without_ any
368*b1cdbd2cSJim Jagielski             // translational component (fixed along with #121921#).
369*b1cdbd2cSJim Jagielski             ::basegfx::B2DRectangle		   aLogShapeBounds;
370*b1cdbd2cSJim Jagielski             const ::basegfx::B2DRectangle& rNominalShapeBoundsPixel(
371*b1cdbd2cSJim Jagielski                 shapeArea2AreaPixel( rCanvasTransform,
372*b1cdbd2cSJim Jagielski                                      ::canvas::tools::calcTransformedRectBounds(
373*b1cdbd2cSJim Jagielski                                          aLogShapeBounds,
374*b1cdbd2cSJim Jagielski                                          ::basegfx::B2DRectangle(0.0,0.0,1.0,1.0),
375*b1cdbd2cSJim Jagielski                                          aNonTranslationalShapeTransformation ) ) );
376*b1cdbd2cSJim Jagielski 
377*b1cdbd2cSJim Jagielski             // create (or resize) sprite with sprite's pixel size, if
378*b1cdbd2cSJim Jagielski             // not done already
379*b1cdbd2cSJim Jagielski             const ::basegfx::B2DSize& rSpriteSizePixel(rSpriteBoundsPixel.getRange());
380*b1cdbd2cSJim Jagielski             if( !mpSprite )
381*b1cdbd2cSJim Jagielski             {
382*b1cdbd2cSJim Jagielski                 mpSprite.reset(
383*b1cdbd2cSJim Jagielski                     new AnimatedSprite( mpViewLayer,
384*b1cdbd2cSJim Jagielski                                         rSpriteSizePixel,
385*b1cdbd2cSJim Jagielski                                         nPrio ));
386*b1cdbd2cSJim Jagielski             }
387*b1cdbd2cSJim Jagielski             else
388*b1cdbd2cSJim Jagielski             {
389*b1cdbd2cSJim Jagielski                 // TODO(F2): when the sprite _actually_ gets resized,
390*b1cdbd2cSJim Jagielski                 // content needs a repaint!
391*b1cdbd2cSJim Jagielski                 mpSprite->resize( rSpriteSizePixel );
392*b1cdbd2cSJim Jagielski             }
393*b1cdbd2cSJim Jagielski 
394*b1cdbd2cSJim Jagielski             ENSURE_OR_RETURN_FALSE( mpSprite, "ViewShape::renderSprite(): No sprite" );
395*b1cdbd2cSJim Jagielski 
396*b1cdbd2cSJim Jagielski             VERBOSE_TRACE( "ViewShape::renderSprite(): Rendering sprite 0x%X",
397*b1cdbd2cSJim Jagielski                            mpSprite.get() );
398*b1cdbd2cSJim Jagielski 
399*b1cdbd2cSJim Jagielski 
400*b1cdbd2cSJim Jagielski             // always show the sprite (might have been hidden before)
401*b1cdbd2cSJim Jagielski             mpSprite->show();
402*b1cdbd2cSJim Jagielski 
403*b1cdbd2cSJim Jagielski             // determine center of sprite output position in pixel
404*b1cdbd2cSJim Jagielski             // (assumption here: all shape transformations have the
405*b1cdbd2cSJim Jagielski             // shape center as the pivot point). From that, subtract
406*b1cdbd2cSJim Jagielski             // distance of rSpriteBoundsPixel's left, top edge from
407*b1cdbd2cSJim Jagielski             // rShapeBoundsPixel's center. This moves the sprite at
408*b1cdbd2cSJim Jagielski             // the appropriate output position within the virtual
409*b1cdbd2cSJim Jagielski             // rShapeBoundsPixel area.
410*b1cdbd2cSJim Jagielski             ::basegfx::B2DPoint aSpritePosPixel( rBounds.getCenter() );
411*b1cdbd2cSJim Jagielski             aSpritePosPixel *= rCanvasTransform;
412*b1cdbd2cSJim Jagielski             aSpritePosPixel -= rShapeBoundsPixel.getCenter() - rSpriteBoundsPixel.getMinimum();
413*b1cdbd2cSJim Jagielski 
414*b1cdbd2cSJim Jagielski             // the difference between rShapeBoundsPixel and
415*b1cdbd2cSJim Jagielski             // rSpriteBoundsPixel upper, left corner is: the offset we
416*b1cdbd2cSJim Jagielski             // have to move sprite output to the right, top (to make
417*b1cdbd2cSJim Jagielski             // the desired subset content visible at all)
418*b1cdbd2cSJim Jagielski             const ::basegfx::B2DSize& rSpriteCorrectionOffset(
419*b1cdbd2cSJim Jagielski                 rSpriteBoundsPixel.getMinimum() - rNominalShapeBoundsPixel.getMinimum() );
420*b1cdbd2cSJim Jagielski 
421*b1cdbd2cSJim Jagielski             // offset added top, left for anti-aliasing (otherwise,
422*b1cdbd2cSJim Jagielski             // shapes fully filling the sprite will have anti-aliased
423*b1cdbd2cSJim Jagielski             // pixel cut off)
424*b1cdbd2cSJim Jagielski             const ::basegfx::B2DSize aAAOffset(
425*b1cdbd2cSJim Jagielski                 ::cppcanvas::Canvas::ANTIALIASING_EXTRA_SIZE,
426*b1cdbd2cSJim Jagielski                 ::cppcanvas::Canvas::ANTIALIASING_EXTRA_SIZE );
427*b1cdbd2cSJim Jagielski 
428*b1cdbd2cSJim Jagielski             // set pixel output offset to sprite: we always leave
429*b1cdbd2cSJim Jagielski             // ANTIALIASING_EXTRA_SIZE room atop and to the left, and,
430*b1cdbd2cSJim Jagielski             // what's more, for subsetted shapes, we _have_ to cancel
431*b1cdbd2cSJim Jagielski             // the effect of the shape renderer outputting the subset
432*b1cdbd2cSJim Jagielski             // at its absolute position inside the shape, instead of
433*b1cdbd2cSJim Jagielski             // at the origin.
434*b1cdbd2cSJim Jagielski             // NOTE: As for now, sprites are always positioned on
435*b1cdbd2cSJim Jagielski             // integer pixel positions on screen, have to round to
436*b1cdbd2cSJim Jagielski             // nearest integer here, too (fixed along with #121921#)
437*b1cdbd2cSJim Jagielski             mpSprite->setPixelOffset(
438*b1cdbd2cSJim Jagielski                 aAAOffset - ::basegfx::B2DSize(
439*b1cdbd2cSJim Jagielski                     ::basegfx::fround( rSpriteCorrectionOffset.getX() ),
440*b1cdbd2cSJim Jagielski                     ::basegfx::fround( rSpriteCorrectionOffset.getY() ) ) );
441*b1cdbd2cSJim Jagielski 
442*b1cdbd2cSJim Jagielski             // always set sprite position and transformation, since
443*b1cdbd2cSJim Jagielski             // they do not relate directly to the update flags
444*b1cdbd2cSJim Jagielski             // (e.g. sprite position changes when sprite size changes)
445*b1cdbd2cSJim Jagielski             mpSprite->movePixel( aSpritePosPixel );
446*b1cdbd2cSJim Jagielski             mpSprite->transform( getSpriteTransformation( rSpriteSizePixel,
447*b1cdbd2cSJim Jagielski                                                           rOrigBounds.getRange(),
448*b1cdbd2cSJim Jagielski                                                           pAttr ) );
449*b1cdbd2cSJim Jagielski 
450*b1cdbd2cSJim Jagielski 
451*b1cdbd2cSJim Jagielski             // process flags
452*b1cdbd2cSJim Jagielski             // =============
453*b1cdbd2cSJim Jagielski 
454*b1cdbd2cSJim Jagielski             bool bRedrawRequired( mbForceUpdate || (nUpdateFlags & FORCE) );
455*b1cdbd2cSJim Jagielski 
456*b1cdbd2cSJim Jagielski             if( mbForceUpdate || (nUpdateFlags & ALPHA) )
457*b1cdbd2cSJim Jagielski             {
458*b1cdbd2cSJim Jagielski                 mpSprite->setAlpha( (pAttr && pAttr->isAlphaValid()) ?
459*b1cdbd2cSJim Jagielski                                     ::basegfx::clamp(pAttr->getAlpha(),
460*b1cdbd2cSJim Jagielski                                                      0.0,
461*b1cdbd2cSJim Jagielski                                                      1.0) :
462*b1cdbd2cSJim Jagielski                                     1.0 );
463*b1cdbd2cSJim Jagielski             }
464*b1cdbd2cSJim Jagielski             if( mbForceUpdate || (nUpdateFlags & CLIP) )
465*b1cdbd2cSJim Jagielski             {
466*b1cdbd2cSJim Jagielski                 if( pAttr && pAttr->isClipValid() )
467*b1cdbd2cSJim Jagielski                 {
468*b1cdbd2cSJim Jagielski                     ::basegfx::B2DPolyPolygon aClipPoly( pAttr->getClip() );
469*b1cdbd2cSJim Jagielski 
470*b1cdbd2cSJim Jagielski                     // extract linear part of canvas view transformation
471*b1cdbd2cSJim Jagielski                     // (linear means: without translational components)
472*b1cdbd2cSJim Jagielski                     ::basegfx::B2DHomMatrix aViewTransform(
473*b1cdbd2cSJim Jagielski                         mpViewLayer->getTransformation() );
474*b1cdbd2cSJim Jagielski                     aViewTransform.set( 0, 2, 0.0 );
475*b1cdbd2cSJim Jagielski                     aViewTransform.set( 1, 2, 0.0 );
476*b1cdbd2cSJim Jagielski 
477*b1cdbd2cSJim Jagielski                     // make the clip 2*ANTIALIASING_EXTRA_SIZE larger
478*b1cdbd2cSJim Jagielski                     // such that it's again centered over the sprite.
479*b1cdbd2cSJim Jagielski                     aViewTransform.scale(rSpriteSizePixel.getX()/
480*b1cdbd2cSJim Jagielski                                          (rSpriteSizePixel.getX()-2*::cppcanvas::Canvas::ANTIALIASING_EXTRA_SIZE),
481*b1cdbd2cSJim Jagielski                                          rSpriteSizePixel.getY()/
482*b1cdbd2cSJim Jagielski                                          (rSpriteSizePixel.getY()-2*::cppcanvas::Canvas::ANTIALIASING_EXTRA_SIZE));
483*b1cdbd2cSJim Jagielski 
484*b1cdbd2cSJim Jagielski                     // transform clip polygon from view to device
485*b1cdbd2cSJim Jagielski                     // coordinate space
486*b1cdbd2cSJim Jagielski                     aClipPoly.transform( aViewTransform );
487*b1cdbd2cSJim Jagielski 
488*b1cdbd2cSJim Jagielski                     mpSprite->clip( aClipPoly );
489*b1cdbd2cSJim Jagielski                 }
490*b1cdbd2cSJim Jagielski                 else
491*b1cdbd2cSJim Jagielski                     mpSprite->clip();
492*b1cdbd2cSJim Jagielski             }
493*b1cdbd2cSJim Jagielski             if( mbForceUpdate || (nUpdateFlags & CONTENT) )
494*b1cdbd2cSJim Jagielski             {
495*b1cdbd2cSJim Jagielski                 bRedrawRequired = true;
496*b1cdbd2cSJim Jagielski 
497*b1cdbd2cSJim Jagielski                 // TODO(P1): maybe provide some appearance change methods at
498*b1cdbd2cSJim Jagielski                 // the Renderer interface
499*b1cdbd2cSJim Jagielski 
500*b1cdbd2cSJim Jagielski                 // force the renderer to be regenerated below, for the
501*b1cdbd2cSJim Jagielski                 // different attributes to take effect
502*b1cdbd2cSJim Jagielski                 invalidateRenderer();
503*b1cdbd2cSJim Jagielski             }
504*b1cdbd2cSJim Jagielski 
505*b1cdbd2cSJim Jagielski             mbForceUpdate = false;
506*b1cdbd2cSJim Jagielski 
507*b1cdbd2cSJim Jagielski             if( !bRedrawRequired )
508*b1cdbd2cSJim Jagielski                 return true;
509*b1cdbd2cSJim Jagielski 
510*b1cdbd2cSJim Jagielski 
511*b1cdbd2cSJim Jagielski             // sprite needs repaint - output to sprite canvas
512*b1cdbd2cSJim Jagielski             // ==============================================
513*b1cdbd2cSJim Jagielski 
514*b1cdbd2cSJim Jagielski             ::cppcanvas::CanvasSharedPtr pContentCanvas( mpSprite->getContentCanvas() );
515*b1cdbd2cSJim Jagielski 
516*b1cdbd2cSJim Jagielski             return draw( pContentCanvas,
517*b1cdbd2cSJim Jagielski                          rMtf,
518*b1cdbd2cSJim Jagielski                          pAttr,
519*b1cdbd2cSJim Jagielski                          aShapeTransformation,
520*b1cdbd2cSJim Jagielski                          NULL, // clipping is done via Sprite::clip()
521*b1cdbd2cSJim Jagielski                          rSubsets );
522*b1cdbd2cSJim Jagielski         }
523*b1cdbd2cSJim Jagielski 
render(const::cppcanvas::CanvasSharedPtr & rDestinationCanvas,const GDIMetaFileSharedPtr & rMtf,const::basegfx::B2DRectangle & rBounds,const::basegfx::B2DRectangle & rUpdateBounds,int nUpdateFlags,const ShapeAttributeLayerSharedPtr & pAttr,const VectorOfDocTreeNodes & rSubsets,bool bIsVisible) const524*b1cdbd2cSJim Jagielski         bool ViewShape::render( const ::cppcanvas::CanvasSharedPtr&	rDestinationCanvas,
525*b1cdbd2cSJim Jagielski                                 const GDIMetaFileSharedPtr&			rMtf,
526*b1cdbd2cSJim Jagielski                                 const ::basegfx::B2DRectangle&		rBounds,
527*b1cdbd2cSJim Jagielski                                 const ::basegfx::B2DRectangle&		rUpdateBounds,
528*b1cdbd2cSJim Jagielski                                 int									nUpdateFlags,
529*b1cdbd2cSJim Jagielski                                 const ShapeAttributeLayerSharedPtr&	pAttr,
530*b1cdbd2cSJim Jagielski                                 const VectorOfDocTreeNodes&			rSubsets,
531*b1cdbd2cSJim Jagielski                                 bool 								bIsVisible ) const
532*b1cdbd2cSJim Jagielski         {
533*b1cdbd2cSJim Jagielski             RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::ViewShape::render()" );
534*b1cdbd2cSJim Jagielski 
535*b1cdbd2cSJim Jagielski             // TODO(P1): For multiple views, it might pay off to reorg Shape and ViewShape,
536*b1cdbd2cSJim Jagielski             // in that all the common setup steps here are refactored to Shape (would then
537*b1cdbd2cSJim Jagielski             // have to be performed only _once_ per Shape paint).
538*b1cdbd2cSJim Jagielski 
539*b1cdbd2cSJim Jagielski             if( !bIsVisible )
540*b1cdbd2cSJim Jagielski             {
541*b1cdbd2cSJim Jagielski                 VERBOSE_TRACE( "ViewShape::render(): skipping shape %X", this );
542*b1cdbd2cSJim Jagielski 
543*b1cdbd2cSJim Jagielski                 // shape is invisible, no need to update anything.
544*b1cdbd2cSJim Jagielski                 return true;
545*b1cdbd2cSJim Jagielski             }
546*b1cdbd2cSJim Jagielski 
547*b1cdbd2cSJim Jagielski             // since we have no sprite here, _any_ update request
548*b1cdbd2cSJim Jagielski             // translates into a required redraw.
549*b1cdbd2cSJim Jagielski             bool bRedrawRequired( mbForceUpdate || nUpdateFlags != 0 );
550*b1cdbd2cSJim Jagielski 
551*b1cdbd2cSJim Jagielski             if( (nUpdateFlags & CONTENT) )
552*b1cdbd2cSJim Jagielski             {
553*b1cdbd2cSJim Jagielski                 // TODO(P1): maybe provide some appearance change methods at
554*b1cdbd2cSJim Jagielski                 // the Renderer interface
555*b1cdbd2cSJim Jagielski 
556*b1cdbd2cSJim Jagielski                 // force the renderer to be regenerated below, for the
557*b1cdbd2cSJim Jagielski                 // different attributes to take effect
558*b1cdbd2cSJim Jagielski                 invalidateRenderer();
559*b1cdbd2cSJim Jagielski             }
560*b1cdbd2cSJim Jagielski 
561*b1cdbd2cSJim Jagielski             mbForceUpdate = false;
562*b1cdbd2cSJim Jagielski 
563*b1cdbd2cSJim Jagielski             if( !bRedrawRequired )
564*b1cdbd2cSJim Jagielski                 return true;
565*b1cdbd2cSJim Jagielski 
566*b1cdbd2cSJim Jagielski             VERBOSE_TRACE( "ViewShape::render(): rendering shape %X at position (%f,%f)",
567*b1cdbd2cSJim Jagielski                            this,
568*b1cdbd2cSJim Jagielski                            rBounds.getMinX(),
569*b1cdbd2cSJim Jagielski                            rBounds.getMinY() );
570*b1cdbd2cSJim Jagielski 
571*b1cdbd2cSJim Jagielski 
572*b1cdbd2cSJim Jagielski             // shape needs repaint - setup all that's needed
573*b1cdbd2cSJim Jagielski             // ---------------------------------------------
574*b1cdbd2cSJim Jagielski 
575*b1cdbd2cSJim Jagielski             boost::optional<basegfx::B2DPolyPolygon> aClip;
576*b1cdbd2cSJim Jagielski 
577*b1cdbd2cSJim Jagielski             if( pAttr )
578*b1cdbd2cSJim Jagielski             {
579*b1cdbd2cSJim Jagielski                 // setup clip poly
580*b1cdbd2cSJim Jagielski                 if( pAttr->isClipValid() )
581*b1cdbd2cSJim Jagielski                     aClip.reset( pAttr->getClip() );
582*b1cdbd2cSJim Jagielski 
583*b1cdbd2cSJim Jagielski                 // emulate global shape alpha by first rendering into
584*b1cdbd2cSJim Jagielski                 // a temp bitmap, and then to screen (this would have
585*b1cdbd2cSJim Jagielski                 // been much easier if we'd be currently a sprite -
586*b1cdbd2cSJim Jagielski                 // see above)
587*b1cdbd2cSJim Jagielski                 if( pAttr->isAlphaValid() )
588*b1cdbd2cSJim Jagielski                 {
589*b1cdbd2cSJim Jagielski                     const double nAlpha( pAttr->getAlpha() );
590*b1cdbd2cSJim Jagielski 
591*b1cdbd2cSJim Jagielski                     if( !::basegfx::fTools::equalZero( nAlpha ) &&
592*b1cdbd2cSJim Jagielski                         !::rtl::math::approxEqual(nAlpha, 1.0) )
593*b1cdbd2cSJim Jagielski                     {
594*b1cdbd2cSJim Jagielski                         // render with global alpha - have to prepare
595*b1cdbd2cSJim Jagielski                         // a bitmap, and render that with modulated
596*b1cdbd2cSJim Jagielski                         // alpha
597*b1cdbd2cSJim Jagielski                         // -------------------------------------------
598*b1cdbd2cSJim Jagielski 
599*b1cdbd2cSJim Jagielski                         const ::basegfx::B2DHomMatrix aTransform(
600*b1cdbd2cSJim Jagielski                             getShapeTransformation( rBounds,
601*b1cdbd2cSJim Jagielski                                                     pAttr ) );
602*b1cdbd2cSJim Jagielski 
603*b1cdbd2cSJim Jagielski                         // TODO(P1): Should the view transform some
604*b1cdbd2cSJim Jagielski                         // day contain rotation/shear, transforming
605*b1cdbd2cSJim Jagielski                         // the original bounds with the total
606*b1cdbd2cSJim Jagielski                         // transformation might result in smaller
607*b1cdbd2cSJim Jagielski                         // overall bounds.
608*b1cdbd2cSJim Jagielski 
609*b1cdbd2cSJim Jagielski                         // determine output rect of _shape update
610*b1cdbd2cSJim Jagielski                         // area_ in device pixel
611*b1cdbd2cSJim Jagielski                         const ::basegfx::B2DHomMatrix aCanvasTransform(
612*b1cdbd2cSJim Jagielski                             rDestinationCanvas->getTransformation() );
613*b1cdbd2cSJim Jagielski                         ::basegfx::B2DRectangle aTmpRect;
614*b1cdbd2cSJim Jagielski                         ::canvas::tools::calcTransformedRectBounds( aTmpRect,
615*b1cdbd2cSJim Jagielski                                                                     rUpdateBounds,
616*b1cdbd2cSJim Jagielski                                                                     aCanvasTransform );
617*b1cdbd2cSJim Jagielski 
618*b1cdbd2cSJim Jagielski                         // pixel size of cache bitmap: round up to
619*b1cdbd2cSJim Jagielski                         // nearest int
620*b1cdbd2cSJim Jagielski                         const ::basegfx::B2ISize aBmpSize( static_cast<sal_Int32>( aTmpRect.getWidth() )+1,
621*b1cdbd2cSJim Jagielski                                                            static_cast<sal_Int32>( aTmpRect.getHeight() )+1 );
622*b1cdbd2cSJim Jagielski 
623*b1cdbd2cSJim Jagielski                         // try to fetch temporary surface for alpha
624*b1cdbd2cSJim Jagielski                         // compositing (to achieve the global alpha
625*b1cdbd2cSJim Jagielski                         // blend effect, have to first render shape as
626*b1cdbd2cSJim Jagielski                         // a whole, then blit that surface with global
627*b1cdbd2cSJim Jagielski                         // alpha to the destination)
628*b1cdbd2cSJim Jagielski                         const RendererCacheVector::iterator aCompositingSurface(
629*b1cdbd2cSJim Jagielski                             getCacheEntry( rDestinationCanvas ) );
630*b1cdbd2cSJim Jagielski 
631*b1cdbd2cSJim Jagielski                         if( !aCompositingSurface->mpLastBitmapCanvas ||
632*b1cdbd2cSJim Jagielski                             aCompositingSurface->mpLastBitmapCanvas->getSize() != aBmpSize )
633*b1cdbd2cSJim Jagielski                         {
634*b1cdbd2cSJim Jagielski                             // create a bitmap of appropriate size
635*b1cdbd2cSJim Jagielski                             ::cppcanvas::BitmapSharedPtr pBitmap(
636*b1cdbd2cSJim Jagielski                                 ::cppcanvas::BaseGfxFactory::getInstance().createAlphaBitmap(
637*b1cdbd2cSJim Jagielski                                     rDestinationCanvas,
638*b1cdbd2cSJim Jagielski                                     aBmpSize ) );
639*b1cdbd2cSJim Jagielski 
640*b1cdbd2cSJim Jagielski                             ENSURE_OR_THROW(pBitmap,
641*b1cdbd2cSJim Jagielski                                              "ViewShape::render(): Could not create compositing surface");
642*b1cdbd2cSJim Jagielski 
643*b1cdbd2cSJim Jagielski                             aCompositingSurface->mpDestinationCanvas = rDestinationCanvas;
644*b1cdbd2cSJim Jagielski                             aCompositingSurface->mpLastBitmap		 = pBitmap;
645*b1cdbd2cSJim Jagielski                             aCompositingSurface->mpLastBitmapCanvas	 = pBitmap->getBitmapCanvas();
646*b1cdbd2cSJim Jagielski                         }
647*b1cdbd2cSJim Jagielski 
648*b1cdbd2cSJim Jagielski                         // buffer aCompositingSurface iterator content
649*b1cdbd2cSJim Jagielski                         // - said one might get invalidated during
650*b1cdbd2cSJim Jagielski                         // draw() below.
651*b1cdbd2cSJim Jagielski                         ::cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas(
652*b1cdbd2cSJim Jagielski                             aCompositingSurface->mpLastBitmapCanvas );
653*b1cdbd2cSJim Jagielski 
654*b1cdbd2cSJim Jagielski                         ::cppcanvas::BitmapSharedPtr pBitmap(
655*b1cdbd2cSJim Jagielski                             aCompositingSurface->mpLastBitmap);
656*b1cdbd2cSJim Jagielski 
657*b1cdbd2cSJim Jagielski                         // setup bitmap canvas transformation -
658*b1cdbd2cSJim Jagielski                         // which happens to be the destination
659*b1cdbd2cSJim Jagielski                         // canvas transformation without any
660*b1cdbd2cSJim Jagielski                         // translational components.
661*b1cdbd2cSJim Jagielski                         //
662*b1cdbd2cSJim Jagielski                         // But then, the render transformation as
663*b1cdbd2cSJim Jagielski                         // calculated by getShapeTransformation()
664*b1cdbd2cSJim Jagielski                         // above outputs the shape at its real
665*b1cdbd2cSJim Jagielski                         // destination position. Thus, we have to
666*b1cdbd2cSJim Jagielski                         // offset the output back to the origin,
667*b1cdbd2cSJim Jagielski                         // for which we simply plug in the
668*b1cdbd2cSJim Jagielski                         // negative position of the left, top edge
669*b1cdbd2cSJim Jagielski                         // of the shape's bound rect in device
670*b1cdbd2cSJim Jagielski                         // pixel into aLinearTransform below.
671*b1cdbd2cSJim Jagielski                         ::basegfx::B2DHomMatrix aAdjustedCanvasTransform( aCanvasTransform );
672*b1cdbd2cSJim Jagielski                         aAdjustedCanvasTransform.translate( -aTmpRect.getMinX(),
673*b1cdbd2cSJim Jagielski                                                             -aTmpRect.getMinY() );
674*b1cdbd2cSJim Jagielski 
675*b1cdbd2cSJim Jagielski                         pBitmapCanvas->setTransformation( aAdjustedCanvasTransform );
676*b1cdbd2cSJim Jagielski 
677*b1cdbd2cSJim Jagielski                         // TODO(P2): If no update flags, or only
678*b1cdbd2cSJim Jagielski                         // alpha_update is set, we can save us the
679*b1cdbd2cSJim Jagielski                         // rendering into the bitmap (uh, it's not
680*b1cdbd2cSJim Jagielski                         // _that_ easy - for a forced redraw,
681*b1cdbd2cSJim Jagielski                         // e.g. when ending an animation, we always
682*b1cdbd2cSJim Jagielski                         // get UPDATE_FORCE here).
683*b1cdbd2cSJim Jagielski 
684*b1cdbd2cSJim Jagielski                         // render into this bitmap
685*b1cdbd2cSJim Jagielski                         if( !draw( pBitmapCanvas,
686*b1cdbd2cSJim Jagielski                                    rMtf,
687*b1cdbd2cSJim Jagielski                                    pAttr,
688*b1cdbd2cSJim Jagielski                                    aTransform,
689*b1cdbd2cSJim Jagielski                                    !aClip ? NULL : &(*aClip),
690*b1cdbd2cSJim Jagielski                                    rSubsets ) )
691*b1cdbd2cSJim Jagielski                         {
692*b1cdbd2cSJim Jagielski                             return false;
693*b1cdbd2cSJim Jagielski                         }
694*b1cdbd2cSJim Jagielski 
695*b1cdbd2cSJim Jagielski                         // render bitmap to screen, with given global
696*b1cdbd2cSJim Jagielski                         // alpha. Since the bitmap already contains
697*b1cdbd2cSJim Jagielski                         // pixel-equivalent output, we have to use the
698*b1cdbd2cSJim Jagielski                         // inverse view transformation, adjusted with
699*b1cdbd2cSJim Jagielski                         // the final shape output position (note:
700*b1cdbd2cSJim Jagielski                         // cannot simply change the view
701*b1cdbd2cSJim Jagielski                         // transformation here, as that would affect a
702*b1cdbd2cSJim Jagielski                         // possibly set clip!)
703*b1cdbd2cSJim Jagielski                         ::basegfx::B2DHomMatrix aBitmapTransform( aCanvasTransform );
704*b1cdbd2cSJim Jagielski                         OSL_ENSURE( aBitmapTransform.isInvertible(),
705*b1cdbd2cSJim Jagielski                                     "ViewShape::render(): View transformation is singular!" );
706*b1cdbd2cSJim Jagielski 
707*b1cdbd2cSJim Jagielski                         aBitmapTransform.invert();
708*b1cdbd2cSJim Jagielski 
709*b1cdbd2cSJim Jagielski                         const basegfx::B2DHomMatrix aTranslation(basegfx::tools::createTranslateB2DHomMatrix(
710*b1cdbd2cSJim Jagielski                             aTmpRect.getMinX(), aTmpRect.getMinY()));
711*b1cdbd2cSJim Jagielski 
712*b1cdbd2cSJim Jagielski                         aBitmapTransform = aBitmapTransform * aTranslation;
713*b1cdbd2cSJim Jagielski                         pBitmap->setTransformation( aBitmapTransform );
714*b1cdbd2cSJim Jagielski 
715*b1cdbd2cSJim Jagielski                         // finally, render bitmap alpha-modulated
716*b1cdbd2cSJim Jagielski                         pBitmap->drawAlphaModulated( nAlpha );
717*b1cdbd2cSJim Jagielski 
718*b1cdbd2cSJim Jagielski                         return true;
719*b1cdbd2cSJim Jagielski                     }
720*b1cdbd2cSJim Jagielski                 }
721*b1cdbd2cSJim Jagielski             }
722*b1cdbd2cSJim Jagielski 
723*b1cdbd2cSJim Jagielski             // retrieve shape transformation, _with_ shape translation
724*b1cdbd2cSJim Jagielski             // to actual page position.
725*b1cdbd2cSJim Jagielski             const ::basegfx::B2DHomMatrix aTransform(
726*b1cdbd2cSJim Jagielski                 getShapeTransformation( rBounds,
727*b1cdbd2cSJim Jagielski                                         pAttr ) );
728*b1cdbd2cSJim Jagielski 
729*b1cdbd2cSJim Jagielski             return draw( rDestinationCanvas,
730*b1cdbd2cSJim Jagielski                          rMtf,
731*b1cdbd2cSJim Jagielski                          pAttr,
732*b1cdbd2cSJim Jagielski                          aTransform,
733*b1cdbd2cSJim Jagielski                          !aClip ? NULL : &(*aClip),
734*b1cdbd2cSJim Jagielski                          rSubsets );
735*b1cdbd2cSJim Jagielski         }
736*b1cdbd2cSJim Jagielski 
737*b1cdbd2cSJim Jagielski 
738*b1cdbd2cSJim Jagielski         // -------------------------------------------------------------------------------------
739*b1cdbd2cSJim Jagielski 
ViewShape(const ViewLayerSharedPtr & rViewLayer)740*b1cdbd2cSJim Jagielski         ViewShape::ViewShape( const ViewLayerSharedPtr& rViewLayer ) :
741*b1cdbd2cSJim Jagielski             mpViewLayer( rViewLayer ),
742*b1cdbd2cSJim Jagielski             maRenderers(),
743*b1cdbd2cSJim Jagielski             mpSprite(),
744*b1cdbd2cSJim Jagielski             mbAnimationMode( false ),
745*b1cdbd2cSJim Jagielski             mbForceUpdate( true )
746*b1cdbd2cSJim Jagielski         {
747*b1cdbd2cSJim Jagielski             ENSURE_OR_THROW( mpViewLayer, "ViewShape::ViewShape(): Invalid View" );
748*b1cdbd2cSJim Jagielski         }
749*b1cdbd2cSJim Jagielski 
getViewLayer() const750*b1cdbd2cSJim Jagielski         ViewLayerSharedPtr ViewShape::getViewLayer() const
751*b1cdbd2cSJim Jagielski         {
752*b1cdbd2cSJim Jagielski             return mpViewLayer;
753*b1cdbd2cSJim Jagielski         }
754*b1cdbd2cSJim Jagielski 
getCacheEntry(const::cppcanvas::CanvasSharedPtr & rDestinationCanvas) const755*b1cdbd2cSJim Jagielski         ViewShape::RendererCacheVector::iterator ViewShape::getCacheEntry( const ::cppcanvas::CanvasSharedPtr&	rDestinationCanvas ) const
756*b1cdbd2cSJim Jagielski         {
757*b1cdbd2cSJim Jagielski             // lookup destination canvas - is there already a renderer
758*b1cdbd2cSJim Jagielski             // created for that target?
759*b1cdbd2cSJim Jagielski             RendererCacheVector::iterator 		aIter;
760*b1cdbd2cSJim Jagielski             const RendererCacheVector::iterator aEnd( maRenderers.end() );
761*b1cdbd2cSJim Jagielski 
762*b1cdbd2cSJim Jagielski             // already there?
763*b1cdbd2cSJim Jagielski             if( (aIter=::std::find_if( maRenderers.begin(),
764*b1cdbd2cSJim Jagielski                                        aEnd,
765*b1cdbd2cSJim Jagielski                                        ::boost::bind(
766*b1cdbd2cSJim Jagielski                                            ::std::equal_to< ::cppcanvas::CanvasSharedPtr >(),
767*b1cdbd2cSJim Jagielski                                            ::boost::cref( rDestinationCanvas ),
768*b1cdbd2cSJim Jagielski                                            ::boost::bind(
769*b1cdbd2cSJim Jagielski                                                &RendererCacheEntry::getDestinationCanvas,
770*b1cdbd2cSJim Jagielski                                                _1 ) ) ) ) == aEnd )
771*b1cdbd2cSJim Jagielski             {
772*b1cdbd2cSJim Jagielski                 if( maRenderers.size() >= MAX_RENDER_CACHE_ENTRIES )
773*b1cdbd2cSJim Jagielski                 {
774*b1cdbd2cSJim Jagielski                     // cache size exceeded - prune entries. For now,
775*b1cdbd2cSJim Jagielski                     // simply remove the first one, which of course
776*b1cdbd2cSJim Jagielski                     // breaks for more complex access schemes. But in
777*b1cdbd2cSJim Jagielski                     // general, this leads to most recently used
778*b1cdbd2cSJim Jagielski                     // entries to reside at the end of the vector.
779*b1cdbd2cSJim Jagielski                     maRenderers.erase( maRenderers.begin() );
780*b1cdbd2cSJim Jagielski 
781*b1cdbd2cSJim Jagielski                     // ATTENTION: after this, both aIter and aEnd are
782*b1cdbd2cSJim Jagielski                     // invalid!
783*b1cdbd2cSJim Jagielski                 }
784*b1cdbd2cSJim Jagielski 
785*b1cdbd2cSJim Jagielski                 // not yet in cache - add default-constructed cache
786*b1cdbd2cSJim Jagielski                 // entry, to have something to return
787*b1cdbd2cSJim Jagielski                 maRenderers.push_back( RendererCacheEntry() );
788*b1cdbd2cSJim Jagielski                 aIter = maRenderers.end()-1;
789*b1cdbd2cSJim Jagielski             }
790*b1cdbd2cSJim Jagielski 
791*b1cdbd2cSJim Jagielski             return aIter;
792*b1cdbd2cSJim Jagielski         }
793*b1cdbd2cSJim Jagielski 
getRenderer(const::cppcanvas::CanvasSharedPtr & rDestinationCanvas,const GDIMetaFileSharedPtr & rMtf,const ShapeAttributeLayerSharedPtr & rAttr) const794*b1cdbd2cSJim Jagielski         ::cppcanvas::RendererSharedPtr ViewShape::getRenderer( const ::cppcanvas::CanvasSharedPtr&	rDestinationCanvas,
795*b1cdbd2cSJim Jagielski                                                                const GDIMetaFileSharedPtr&			rMtf,
796*b1cdbd2cSJim Jagielski                                                                const ShapeAttributeLayerSharedPtr&	rAttr ) const
797*b1cdbd2cSJim Jagielski         {
798*b1cdbd2cSJim Jagielski             // lookup destination canvas - is there already a renderer
799*b1cdbd2cSJim Jagielski             // created for that target?
800*b1cdbd2cSJim Jagielski             const RendererCacheVector::iterator aIter(
801*b1cdbd2cSJim Jagielski                 getCacheEntry( rDestinationCanvas ) );
802*b1cdbd2cSJim Jagielski 
803*b1cdbd2cSJim Jagielski             // now we have a valid entry, either way. call prefetch()
804*b1cdbd2cSJim Jagielski             // on it, nevertheless - maybe the metafile changed, and
805*b1cdbd2cSJim Jagielski             // the renderer still needs an update (prefetch() will
806*b1cdbd2cSJim Jagielski             // detect that)
807*b1cdbd2cSJim Jagielski             if( prefetch( *aIter,
808*b1cdbd2cSJim Jagielski                           rDestinationCanvas,
809*b1cdbd2cSJim Jagielski                           rMtf,
810*b1cdbd2cSJim Jagielski                           rAttr ) )
811*b1cdbd2cSJim Jagielski             {
812*b1cdbd2cSJim Jagielski                 return aIter->mpRenderer;
813*b1cdbd2cSJim Jagielski             }
814*b1cdbd2cSJim Jagielski             else
815*b1cdbd2cSJim Jagielski             {
816*b1cdbd2cSJim Jagielski                 // prefetch failed - renderer is invalid
817*b1cdbd2cSJim Jagielski                 return ::cppcanvas::RendererSharedPtr();
818*b1cdbd2cSJim Jagielski             }
819*b1cdbd2cSJim Jagielski         }
820*b1cdbd2cSJim Jagielski 
invalidateRenderer() const821*b1cdbd2cSJim Jagielski         void ViewShape::invalidateRenderer() const
822*b1cdbd2cSJim Jagielski         {
823*b1cdbd2cSJim Jagielski             // simply clear the cache. Subsequent getRenderer() calls
824*b1cdbd2cSJim Jagielski             // will regenerate the Renderers.
825*b1cdbd2cSJim Jagielski             maRenderers.clear();
826*b1cdbd2cSJim Jagielski         }
827*b1cdbd2cSJim Jagielski 
getAntialiasingBorder() const828*b1cdbd2cSJim Jagielski         ::basegfx::B2DSize ViewShape::getAntialiasingBorder() const
829*b1cdbd2cSJim Jagielski         {
830*b1cdbd2cSJim Jagielski             ENSURE_OR_THROW( mpViewLayer->getCanvas(),
831*b1cdbd2cSJim Jagielski                               "ViewShape::getAntialiasingBorder(): Invalid ViewLayer canvas" );
832*b1cdbd2cSJim Jagielski 
833*b1cdbd2cSJim Jagielski             const ::basegfx::B2DHomMatrix& rViewTransform(
834*b1cdbd2cSJim Jagielski                 mpViewLayer->getTransformation() );
835*b1cdbd2cSJim Jagielski 
836*b1cdbd2cSJim Jagielski             // TODO(F1): As a quick shortcut (did not want to invert
837*b1cdbd2cSJim Jagielski             // whole matrix here), taking only scale components of
838*b1cdbd2cSJim Jagielski             // view transformation matrix. This will be wrong when
839*b1cdbd2cSJim Jagielski             // e.g. shearing is involved.
840*b1cdbd2cSJim Jagielski             const double nXBorder( ::cppcanvas::Canvas::ANTIALIASING_EXTRA_SIZE / rViewTransform.get(0,0) );
841*b1cdbd2cSJim Jagielski             const double nYBorder( ::cppcanvas::Canvas::ANTIALIASING_EXTRA_SIZE / rViewTransform.get(1,1) );
842*b1cdbd2cSJim Jagielski 
843*b1cdbd2cSJim Jagielski             return ::basegfx::B2DSize( nXBorder,
844*b1cdbd2cSJim Jagielski                                        nYBorder );
845*b1cdbd2cSJim Jagielski         }
846*b1cdbd2cSJim Jagielski 
enterAnimationMode()847*b1cdbd2cSJim Jagielski         bool ViewShape::enterAnimationMode()
848*b1cdbd2cSJim Jagielski         {
849*b1cdbd2cSJim Jagielski             mbForceUpdate   = true;
850*b1cdbd2cSJim Jagielski             mbAnimationMode = true;
851*b1cdbd2cSJim Jagielski 
852*b1cdbd2cSJim Jagielski             return true;
853*b1cdbd2cSJim Jagielski         }
854*b1cdbd2cSJim Jagielski 
leaveAnimationMode()855*b1cdbd2cSJim Jagielski         void ViewShape::leaveAnimationMode()
856*b1cdbd2cSJim Jagielski         {
857*b1cdbd2cSJim Jagielski             mpSprite.reset();
858*b1cdbd2cSJim Jagielski             mbAnimationMode = false;
859*b1cdbd2cSJim Jagielski             mbForceUpdate   = true;
860*b1cdbd2cSJim Jagielski         }
861*b1cdbd2cSJim Jagielski 
update(const GDIMetaFileSharedPtr & rMtf,const RenderArgs & rArgs,int nUpdateFlags,bool bIsVisible) const862*b1cdbd2cSJim Jagielski         bool ViewShape::update( const GDIMetaFileSharedPtr&	rMtf,
863*b1cdbd2cSJim Jagielski                                 const RenderArgs&			rArgs,
864*b1cdbd2cSJim Jagielski                                 int							nUpdateFlags,
865*b1cdbd2cSJim Jagielski                                 bool						bIsVisible ) const
866*b1cdbd2cSJim Jagielski         {
867*b1cdbd2cSJim Jagielski             RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::ViewShape::update()" );
868*b1cdbd2cSJim Jagielski             ENSURE_OR_RETURN_FALSE( mpViewLayer->getCanvas(), "ViewShape::update(): Invalid layer canvas" );
869*b1cdbd2cSJim Jagielski 
870*b1cdbd2cSJim Jagielski             // Shall we render to a sprite, or to a plain canvas?
871*b1cdbd2cSJim Jagielski             if( isBackgroundDetached() )
872*b1cdbd2cSJim Jagielski                 return renderSprite( mpViewLayer,
873*b1cdbd2cSJim Jagielski                                      rMtf,
874*b1cdbd2cSJim Jagielski                                      rArgs.maOrigBounds,
875*b1cdbd2cSJim Jagielski                                      rArgs.maBounds,
876*b1cdbd2cSJim Jagielski                                      rArgs.maUnitBounds,
877*b1cdbd2cSJim Jagielski                                      nUpdateFlags,
878*b1cdbd2cSJim Jagielski                                      rArgs.mrAttr,
879*b1cdbd2cSJim Jagielski                                      rArgs.mrSubsets,
880*b1cdbd2cSJim Jagielski                                      rArgs.mnShapePriority,
881*b1cdbd2cSJim Jagielski                                      bIsVisible );
882*b1cdbd2cSJim Jagielski             else
883*b1cdbd2cSJim Jagielski                 return render( mpViewLayer->getCanvas(),
884*b1cdbd2cSJim Jagielski                                rMtf,
885*b1cdbd2cSJim Jagielski                                rArgs.maBounds,
886*b1cdbd2cSJim Jagielski                                rArgs.maUpdateBounds,
887*b1cdbd2cSJim Jagielski                                nUpdateFlags,
888*b1cdbd2cSJim Jagielski                                rArgs.mrAttr,
889*b1cdbd2cSJim Jagielski                                rArgs.mrSubsets,
890*b1cdbd2cSJim Jagielski                                bIsVisible );
891*b1cdbd2cSJim Jagielski         }
892*b1cdbd2cSJim Jagielski 
893*b1cdbd2cSJim Jagielski     }
894*b1cdbd2cSJim Jagielski }
895