1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_cppcanvas.hxx" 26 27 #include <rtl/logfile.hxx> 28 29 #include <com/sun/star/rendering/XCanvas.hpp> 30 #include <com/sun/star/rendering/TexturingMode.hpp> 31 32 #include <tools/gen.hxx> 33 #include <vcl/canvastools.hxx> 34 35 #include <basegfx/range/b2drectangle.hxx> 36 #include <basegfx/tools/canvastools.hxx> 37 #include <basegfx/polygon/b2dpolypolygon.hxx> 38 #include <basegfx/polygon/b2dpolypolygontools.hxx> 39 #include <basegfx/matrix/b2dhommatrix.hxx> 40 #include <canvas/canvastools.hxx> 41 42 #include <boost/utility.hpp> 43 44 #include "cachedprimitivebase.hxx" 45 #include "polypolyaction.hxx" 46 #include "outdevstate.hxx" 47 #include "mtftools.hxx" 48 49 50 using namespace ::com::sun::star; 51 52 namespace cppcanvas 53 { 54 namespace internal 55 { 56 namespace 57 { 58 class PolyPolyAction : public CachedPrimitiveBase 59 { 60 public: 61 PolyPolyAction( const ::basegfx::B2DPolyPolygon&, 62 const CanvasSharedPtr&, 63 const OutDevState&, 64 bool bFill, 65 bool bStroke ); 66 PolyPolyAction( const ::basegfx::B2DPolyPolygon&, 67 const CanvasSharedPtr&, 68 const OutDevState&, 69 bool bFill, 70 bool bStroke, 71 int nTransparency ); 72 73 virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation, 74 const Subset& rSubset ) const; 75 76 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const; 77 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation, 78 const Subset& rSubset ) const; 79 80 virtual sal_Int32 getActionCount() const; 81 82 private: 83 using Action::render; 84 virtual bool render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive, 85 const ::basegfx::B2DHomMatrix& rTransformation ) const; 86 87 const uno::Reference< rendering::XPolyPolygon2D > mxPolyPoly; 88 const ::basegfx::B2DRange maBounds; 89 const CanvasSharedPtr mpCanvas; 90 91 // stroke color is now implicit: the maState.DeviceColor member 92 rendering::RenderState maState; 93 94 uno::Sequence< double > maFillColor; 95 }; 96 PolyPolyAction(const::basegfx::B2DPolyPolygon & rPolyPoly,const CanvasSharedPtr & rCanvas,const OutDevState & rState,bool bFill,bool bStroke)97 PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon& rPolyPoly, 98 const CanvasSharedPtr& rCanvas, 99 const OutDevState& rState, 100 bool bFill, 101 bool bStroke ) : 102 CachedPrimitiveBase( rCanvas, false ), 103 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas->getUNOCanvas()->getDevice(), rPolyPoly) ), 104 maBounds( ::basegfx::tools::getRange(rPolyPoly) ), 105 mpCanvas( rCanvas ), 106 maState(), 107 maFillColor() 108 { 109 tools::initRenderState(maState,rState); 110 111 if( bFill ) 112 maFillColor = rState.fillColor; 113 114 if( bStroke ) 115 maState.DeviceColor = rState.lineColor; 116 } 117 PolyPolyAction(const::basegfx::B2DPolyPolygon & rPolyPoly,const CanvasSharedPtr & rCanvas,const OutDevState & rState,bool bFill,bool bStroke,int nTransparency)118 PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon& rPolyPoly, 119 const CanvasSharedPtr& rCanvas, 120 const OutDevState& rState, 121 bool bFill, 122 bool bStroke, 123 int nTransparency ) : 124 CachedPrimitiveBase( rCanvas, false ), 125 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas->getUNOCanvas()->getDevice(), rPolyPoly) ), 126 maBounds( ::basegfx::tools::getRange(rPolyPoly) ), 127 mpCanvas( rCanvas ), 128 maState(), 129 maFillColor() 130 { 131 tools::initRenderState(maState,rState); 132 133 if( bFill ) 134 { 135 maFillColor = rState.fillColor; 136 137 if( maFillColor.getLength() < 4 ) 138 maFillColor.realloc( 4 ); 139 140 // TODO(F1): Color management 141 // adapt fill color transparency 142 maFillColor[3] = 1.0 - nTransparency / 100.0; 143 } 144 145 if( bStroke ) 146 { 147 maState.DeviceColor = rState.lineColor; 148 149 if( maState.DeviceColor.getLength() < 4 ) 150 maState.DeviceColor.realloc( 4 ); 151 152 // TODO(F1): Color management 153 // adapt fill color transparency 154 maState.DeviceColor[3] = 1.0 - nTransparency / 100.0; 155 } 156 } 157 render(uno::Reference<rendering::XCachedPrimitive> & rCachedPrimitive,const::basegfx::B2DHomMatrix & rTransformation) const158 bool PolyPolyAction::render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive, 159 const ::basegfx::B2DHomMatrix& rTransformation ) const 160 { 161 RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::PolyPolyAction::render()" ); 162 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::PolyPolyAction: 0x%X", this ); 163 164 rendering::RenderState aLocalState( maState ); 165 ::canvas::tools::prependToRenderState(aLocalState, rTransformation); 166 167 #ifdef SPECIAL_DEBUG 168 aLocalState.Clip.clear(); 169 aLocalState.DeviceColor = 170 ::vcl::unotools::colorToDoubleSequence( mpCanvas->getUNOCanvas()->getDevice(), 171 ::Color( 0x80FF0000 ) ); 172 173 if( maState.Clip.is() ) 174 mpCanvas->getUNOCanvas()->fillPolyPolygon( maState.Clip, 175 mpCanvas->getViewState(), 176 aLocalState ); 177 178 aLocalState.DeviceColor = maState.DeviceColor; 179 #endif 180 181 if( maFillColor.getLength() ) 182 { 183 // TODO(E3): Use DBO's finalizer here, 184 // fillPolyPolygon() might throw 185 const uno::Sequence< double > aTmpColor( aLocalState.DeviceColor ); 186 aLocalState.DeviceColor = maFillColor; 187 188 rCachedPrimitive = mpCanvas->getUNOCanvas()->fillPolyPolygon( mxPolyPoly, 189 mpCanvas->getViewState(), 190 aLocalState ); 191 192 aLocalState.DeviceColor = aTmpColor; 193 } 194 195 if( aLocalState.DeviceColor.getLength() ) 196 { 197 rCachedPrimitive = mpCanvas->getUNOCanvas()->drawPolyPolygon( mxPolyPoly, 198 mpCanvas->getViewState(), 199 aLocalState ); 200 } 201 202 return true; 203 } 204 render(const::basegfx::B2DHomMatrix & rTransformation,const Subset & rSubset) const205 bool PolyPolyAction::render( const ::basegfx::B2DHomMatrix& rTransformation, 206 const Subset& rSubset ) const 207 { 208 // TODO(F1): Split up poly-polygon into polygons, or even 209 // line segments, when subsets are requested. 210 211 // polygon only contains a single action, fail if subset 212 // requests different range 213 if( rSubset.mnSubsetBegin != 0 || 214 rSubset.mnSubsetEnd != 1 ) 215 return false; 216 217 return CachedPrimitiveBase::render( rTransformation ); 218 } 219 getBounds(const::basegfx::B2DHomMatrix & rTransformation) const220 ::basegfx::B2DRange PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const 221 { 222 rendering::RenderState aLocalState( maState ); 223 ::canvas::tools::prependToRenderState(aLocalState, rTransformation); 224 225 return tools::calcDevicePixelBounds( 226 maBounds, 227 mpCanvas->getViewState(), 228 aLocalState ); 229 } 230 getBounds(const::basegfx::B2DHomMatrix & rTransformation,const Subset & rSubset) const231 ::basegfx::B2DRange PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation, 232 const Subset& rSubset ) const 233 { 234 // TODO(F1): Split up poly-polygon into polygons, or even 235 // line segments, when subsets are requested. 236 237 // polygon only contains a single action, empty bounds 238 // if subset requests different range 239 if( rSubset.mnSubsetBegin != 0 || 240 rSubset.mnSubsetEnd != 1 ) 241 return ::basegfx::B2DRange(); 242 243 return getBounds( rTransformation ); 244 } 245 getActionCount() const246 sal_Int32 PolyPolyAction::getActionCount() const 247 { 248 // TODO(F1): Split up poly-polygon into polygons, or even 249 // line segments, when subsets are requested. 250 return 1; 251 } 252 253 254 // ------------------------------------------------------------------------------- 255 256 class TexturedPolyPolyAction : public CachedPrimitiveBase 257 { 258 public: 259 TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPoly, 260 const CanvasSharedPtr& rCanvas, 261 const OutDevState& rState, 262 const rendering::Texture& rTexture ); 263 264 virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation, 265 const Subset& rSubset ) const; 266 267 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const; 268 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation, 269 const Subset& rSubset ) const; 270 271 virtual sal_Int32 getActionCount() const; 272 273 private: 274 using Action::render; 275 virtual bool render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive, 276 const ::basegfx::B2DHomMatrix& rTransformation ) const; 277 278 const uno::Reference< rendering::XPolyPolygon2D > mxPolyPoly; 279 const ::basegfx::B2DRectangle maBounds; 280 const CanvasSharedPtr mpCanvas; 281 282 // stroke color is now implicit: the maState.DeviceColor member 283 rendering::RenderState maState; 284 const rendering::Texture maTexture; 285 }; 286 TexturedPolyPolyAction(const::basegfx::B2DPolyPolygon & rPolyPoly,const CanvasSharedPtr & rCanvas,const OutDevState & rState,const rendering::Texture & rTexture)287 TexturedPolyPolyAction::TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPolyPoly, 288 const CanvasSharedPtr& rCanvas, 289 const OutDevState& rState, 290 const rendering::Texture& rTexture ) : 291 CachedPrimitiveBase( rCanvas, true ), 292 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas->getUNOCanvas()->getDevice(), rPolyPoly) ), 293 maBounds( ::basegfx::tools::getRange(rPolyPoly) ), 294 mpCanvas( rCanvas ), 295 maState(), 296 maTexture( rTexture ) 297 { 298 tools::initRenderState(maState,rState); 299 } 300 render(uno::Reference<rendering::XCachedPrimitive> & rCachedPrimitive,const::basegfx::B2DHomMatrix & rTransformation) const301 bool TexturedPolyPolyAction::render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive, 302 const ::basegfx::B2DHomMatrix& rTransformation ) const 303 { 304 RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::PolyPolyAction::render()" ); 305 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::PolyPolyAction: 0x%X", this ); 306 307 rendering::RenderState aLocalState( maState ); 308 ::canvas::tools::prependToRenderState(aLocalState, rTransformation); 309 310 uno::Sequence< rendering::Texture > aSeq(1); 311 aSeq[0] = maTexture; 312 313 rCachedPrimitive = mpCanvas->getUNOCanvas()->fillTexturedPolyPolygon( mxPolyPoly, 314 mpCanvas->getViewState(), 315 aLocalState, 316 aSeq ); 317 return true; 318 } 319 render(const::basegfx::B2DHomMatrix & rTransformation,const Subset & rSubset) const320 bool TexturedPolyPolyAction::render( const ::basegfx::B2DHomMatrix& rTransformation, 321 const Subset& rSubset ) const 322 { 323 // TODO(F1): Split up poly-polygon into polygons, or even 324 // line segments, when subsets are requested. 325 326 // polygon only contains a single action, fail if subset 327 // requests different range 328 if( rSubset.mnSubsetBegin != 0 || 329 rSubset.mnSubsetEnd != 1 ) 330 return false; 331 332 return CachedPrimitiveBase::render( rTransformation ); 333 } 334 getBounds(const::basegfx::B2DHomMatrix & rTransformation) const335 ::basegfx::B2DRange TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const 336 { 337 rendering::RenderState aLocalState( maState ); 338 ::canvas::tools::prependToRenderState(aLocalState, rTransformation); 339 340 return tools::calcDevicePixelBounds( 341 maBounds, 342 mpCanvas->getViewState(), 343 aLocalState ); 344 } 345 getBounds(const::basegfx::B2DHomMatrix & rTransformation,const Subset & rSubset) const346 ::basegfx::B2DRange TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation, 347 const Subset& rSubset ) const 348 { 349 // TODO(F1): Split up poly-polygon into polygons, or even 350 // line segments, when subsets are requested. 351 352 // polygon only contains a single action, empty bounds 353 // if subset requests different range 354 if( rSubset.mnSubsetBegin != 0 || 355 rSubset.mnSubsetEnd != 1 ) 356 return ::basegfx::B2DRange(); 357 358 return getBounds( rTransformation ); 359 } 360 getActionCount() const361 sal_Int32 TexturedPolyPolyAction::getActionCount() const 362 { 363 // TODO(F1): Split up poly-polygon into polygons, or even 364 // line segments, when subsets are requested. 365 return 1; 366 } 367 368 // ------------------------------------------------------------------------------- 369 370 class StrokedPolyPolyAction : public CachedPrimitiveBase 371 { 372 public: 373 StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPoly, 374 const CanvasSharedPtr& rCanvas, 375 const OutDevState& rState, 376 const rendering::StrokeAttributes& rStrokeAttributes ); 377 378 virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation, 379 const Subset& rSubset ) const; 380 381 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const; 382 virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation, 383 const Subset& rSubset ) const; 384 385 virtual sal_Int32 getActionCount() const; 386 387 private: 388 using Action::render; 389 virtual bool render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive, 390 const ::basegfx::B2DHomMatrix& rTransformation ) const; 391 392 const uno::Reference< rendering::XPolyPolygon2D > mxPolyPoly; 393 const ::basegfx::B2DRectangle maBounds; 394 const CanvasSharedPtr mpCanvas; 395 rendering::RenderState maState; 396 const rendering::StrokeAttributes maStrokeAttributes; 397 }; 398 StrokedPolyPolyAction(const::basegfx::B2DPolyPolygon & rPolyPoly,const CanvasSharedPtr & rCanvas,const OutDevState & rState,const rendering::StrokeAttributes & rStrokeAttributes)399 StrokedPolyPolyAction::StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPolyPoly, 400 const CanvasSharedPtr& rCanvas, 401 const OutDevState& rState, 402 const rendering::StrokeAttributes& rStrokeAttributes ) : 403 CachedPrimitiveBase( rCanvas, false ), 404 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas->getUNOCanvas()->getDevice(), rPolyPoly) ), 405 maBounds( ::basegfx::tools::getRange(rPolyPoly) ), 406 mpCanvas( rCanvas ), 407 maState(), 408 maStrokeAttributes( rStrokeAttributes ) 409 { 410 tools::initRenderState(maState,rState); 411 maState.DeviceColor = rState.lineColor; 412 } 413 render(uno::Reference<rendering::XCachedPrimitive> & rCachedPrimitive,const::basegfx::B2DHomMatrix & rTransformation) const414 bool StrokedPolyPolyAction::render( uno::Reference< rendering::XCachedPrimitive >& rCachedPrimitive, 415 const ::basegfx::B2DHomMatrix& rTransformation ) const 416 { 417 RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::PolyPolyAction::render()" ); 418 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::PolyPolyAction: 0x%X", this ); 419 420 rendering::RenderState aLocalState( maState ); 421 ::canvas::tools::prependToRenderState(aLocalState, rTransformation); 422 423 rCachedPrimitive = mpCanvas->getUNOCanvas()->strokePolyPolygon( mxPolyPoly, 424 mpCanvas->getViewState(), 425 aLocalState, 426 maStrokeAttributes ); 427 return true; 428 } 429 render(const::basegfx::B2DHomMatrix & rTransformation,const Subset & rSubset) const430 bool StrokedPolyPolyAction::render( const ::basegfx::B2DHomMatrix& rTransformation, 431 const Subset& rSubset ) const 432 { 433 // TODO(F1): Split up poly-polygon into polygons, or even 434 // line segments, when subsets are requested. 435 436 // polygon only contains a single action, fail if subset 437 // requests different range 438 if( rSubset.mnSubsetBegin != 0 || 439 rSubset.mnSubsetEnd != 1 ) 440 return false; 441 442 return CachedPrimitiveBase::render( rTransformation ); 443 } 444 getBounds(const::basegfx::B2DHomMatrix & rTransformation) const445 ::basegfx::B2DRange StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const 446 { 447 rendering::RenderState aLocalState( maState ); 448 ::canvas::tools::prependToRenderState(aLocalState, rTransformation); 449 450 return tools::calcDevicePixelBounds( 451 maBounds, 452 mpCanvas->getViewState(), 453 aLocalState ); 454 } 455 getBounds(const::basegfx::B2DHomMatrix & rTransformation,const Subset & rSubset) const456 ::basegfx::B2DRange StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation, 457 const Subset& rSubset ) const 458 { 459 // TODO(F1): Split up poly-polygon into polygons, or even 460 // line segments, when subsets are requested. 461 462 // polygon only contains a single action, empty bounds 463 // if subset requests different range 464 if( rSubset.mnSubsetBegin != 0 || 465 rSubset.mnSubsetEnd != 1 ) 466 return ::basegfx::B2DRange(); 467 468 return getBounds( rTransformation ); 469 } 470 getActionCount() const471 sal_Int32 StrokedPolyPolyAction::getActionCount() const 472 { 473 // TODO(F1): Split up poly-polygon into polygons, or even 474 // line segments, when subsets are requested. 475 return 1; 476 } 477 } 478 createPolyPolyAction(const::basegfx::B2DPolyPolygon & rPoly,const CanvasSharedPtr & rCanvas,const OutDevState & rState)479 ActionSharedPtr PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPoly, 480 const CanvasSharedPtr& rCanvas, 481 const OutDevState& rState ) 482 { 483 OSL_ENSURE( rState.isLineColorSet || rState.isFillColorSet, 484 "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" ); 485 return ActionSharedPtr( new PolyPolyAction( rPoly, rCanvas, rState, 486 rState.isFillColorSet, 487 rState.isLineColorSet ) ); 488 } 489 createPolyPolyAction(const::basegfx::B2DPolyPolygon & rPoly,const CanvasSharedPtr & rCanvas,const OutDevState & rState,const rendering::Texture & rTexture)490 ActionSharedPtr PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPoly, 491 const CanvasSharedPtr& rCanvas, 492 const OutDevState& rState, 493 const rendering::Texture& rTexture ) 494 { 495 return ActionSharedPtr( new TexturedPolyPolyAction( rPoly, rCanvas, rState, rTexture ) ); 496 } 497 createLinePolyPolyAction(const::basegfx::B2DPolyPolygon & rPoly,const CanvasSharedPtr & rCanvas,const OutDevState & rState)498 ActionSharedPtr PolyPolyActionFactory::createLinePolyPolyAction( const ::basegfx::B2DPolyPolygon& rPoly, 499 const CanvasSharedPtr& rCanvas, 500 const OutDevState& rState ) 501 { 502 OSL_ENSURE( rState.isLineColorSet, 503 "PolyPolyActionFactory::createLinePolyPolyAction() called with empty line color" ); 504 505 return ActionSharedPtr( new PolyPolyAction( rPoly, rCanvas, rState, 506 false, 507 rState.isLineColorSet ) ); 508 } 509 createPolyPolyAction(const::basegfx::B2DPolyPolygon & rPoly,const CanvasSharedPtr & rCanvas,const OutDevState & rState,const rendering::StrokeAttributes & rStrokeAttributes)510 ActionSharedPtr PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPoly, 511 const CanvasSharedPtr& rCanvas, 512 const OutDevState& rState, 513 const rendering::StrokeAttributes& rStrokeAttributes ) 514 { 515 OSL_ENSURE( rState.isLineColorSet, 516 "PolyPolyActionFactory::createPolyPolyAction() for strokes called with empty line color" ); 517 return ActionSharedPtr( new StrokedPolyPolyAction( rPoly, rCanvas, rState, rStrokeAttributes ) ); 518 } 519 createPolyPolyAction(const::basegfx::B2DPolyPolygon & rPoly,const CanvasSharedPtr & rCanvas,const OutDevState & rState,int nTransparency)520 ActionSharedPtr PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon& rPoly, 521 const CanvasSharedPtr& rCanvas, 522 const OutDevState& rState, 523 int nTransparency ) 524 { 525 OSL_ENSURE( rState.isLineColorSet || rState.isFillColorSet, 526 "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" ); 527 return ActionSharedPtr( new PolyPolyAction( rPoly, rCanvas, rState, 528 rState.isFillColorSet, 529 rState.isLineColorSet, 530 nTransparency ) ); 531 } 532 533 } 534 } 535