1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008, 2009, 2010, 2014 Henrik Tidefelt
21 #include "shapestypes.h"
22 #include "shapesexceptions.h"
25 #include "angleselect.h"
28 #include "statetypes.h"
29 #include "lighttypes.h"
30 #include "shadingtypes.h"
32 #include "trianglefunctions.h"
33 #include "pagecontentstates.h"
34 #include "continuations.h"
41 using namespace Shapes
;
44 Lang::Drawable2D::Drawable2D( )
47 Lang::Drawable2D::~Drawable2D( )
50 RefCountPtr
< const Lang::Transformed2D
>
51 Lang::Drawable2D::typed_transformed( const Lang::Transform2D
& tf
, const RefCountPtr
< const Lang::Drawable2D
> & self
) const
53 return RefCountPtr
< const Lang::Transformed2D
>( new Lang::Transformed2D( self
, tf
) );
56 RefCountPtr
< const Lang::Geometric2D
>
57 Lang::Drawable2D::transformed( const Lang::Transform2D
& tf
, const RefCountPtr
< const Lang::Geometric2D
> & self
) const
59 return typed_transformed( tf
, self
.down_cast
< const Lang::Drawable2D
>( ) );
62 RefCountPtr
< const Lang::Geometric3D
>
63 Lang::Drawable2D::to3D( const RefCountPtr
< const Lang::Geometric2D
> & self
) const
65 typedef const Lang::Drawable2D SelfType
;
66 RefCountPtr
< SelfType
> typedSelf
= self
.down_cast
< SelfType
>( );
67 if( typedSelf
== NullPtr
< SelfType
>( ) )
69 throw Exceptions::InternalError( "The self-value passed to Drawable2D::to3D was of bad type." );
71 return RefCountPtr
< const Lang::Geometric3D
>( new Lang::Drawable2Din3D( typedSelf
) );
75 Lang::Drawable2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
77 // Not overloading this methods means that there are no tagged objects within this.
81 Lang::Drawable2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
83 // Not overloading this methods means that there are no tagged objects within this.
88 Lang::Drawable2D::gcMark( Kernel::GCMarkedSet
& marked
)
91 RefCountPtr
< const Lang::Class
> Lang::Drawable2D::TypeID
= NullPtr
< const Lang::Class
>( ); /* The value is set in main */
92 TYPEINFOIMPL( Drawable2D
);
93 DISPATCHIMPL( Drawable2D
);
96 Lang::Group2D::Group2D( )
99 Lang::Group2D::~Group2D( )
102 RefCountPtr
< const Lang::Class
> Lang::Group2D::TypeID( new Lang::SystemFinalClass( strrefdup( "Group2D" ) ) );
103 TYPEINFOIMPL( Group2D
);
106 RefCountPtr
< const Lang::Group2D
>
107 Helpers::newGroup2D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
, const RefCountPtr
< const Lang::Drawable2D
> & obj2
, const RefCountPtr
< const Lang::Drawable2D
> & obj1
)
109 RefCountPtr
< const Lang::Group2D
> res
= Lang::THE_NULL2D
;
110 res
= RefCountPtr
< const Lang::GroupPair2D
>( new Lang::GroupPair2D( obj1
,
113 res
= RefCountPtr
< const Lang::GroupPair2D
>( new Lang::GroupPair2D( obj2
,
119 RefCountPtr
< const Lang::Group2D
>
120 Helpers::newGroup2D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
, const RefCountPtr
< const Lang::Drawable2D
> & obj3
, const RefCountPtr
< const Lang::Drawable2D
> & obj2
, const RefCountPtr
< const Lang::Drawable2D
> & obj1
)
122 RefCountPtr
< const Lang::Group2D
> res
= Lang::THE_NULL2D
;
123 res
= RefCountPtr
< const Lang::GroupPair2D
>( new Lang::GroupPair2D( obj1
,
126 res
= RefCountPtr
< const Lang::GroupPair2D
>( new Lang::GroupPair2D( obj2
,
129 res
= RefCountPtr
< const Lang::GroupPair2D
>( new Lang::GroupPair2D( obj3
,
136 Lang::GroupPair2D::GroupPair2D( RefCountPtr
< const Lang::Drawable2D
> car
, RefCountPtr
< const Lang::Group2D
> cdr
, const RefCountPtr
< const Kernel::GraphicsState
> & metaState
)
137 : metaState_( metaState
), car_( car
), cdr_( cdr
)
140 Lang::GroupPair2D::~GroupPair2D( )
144 Lang::GroupPair2D::isNull( ) const
150 Lang::GroupPair2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
152 cdr_
->shipout( os
, pdfState
, tf
);
153 if( pdfState
->graphics_
.synchBlend( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) ) )
157 car_
->shipout( os
, pdfState
, tf
);
160 RefCountPtr
< const Lang::ElementaryPath2D
>
161 Lang::GroupPair2D::bbox( Lang::Drawable2D::BoxType boxType
) const
163 Concrete::Length xmin
= Concrete::HUGE_LENGTH
;
164 Concrete::Length ymin
= Concrete::HUGE_LENGTH
;
165 Concrete::Length xmax
= -Concrete::HUGE_LENGTH
;
166 Concrete::Length ymax
= -Concrete::HUGE_LENGTH
;
168 return bboxAdd( boxType
, xmin
, ymin
, xmax
, ymax
);
171 RefCountPtr
< const Lang::ElementaryPath2D
>
172 Lang::GroupPair2D::bboxAdd( Lang::Drawable2D::BoxType boxType
, Concrete::Length xmin
, Concrete::Length ymin
, Concrete::Length xmax
, Concrete::Length ymax
) const
175 RefCountPtr
< const Lang::ElementaryPath2D
> carbbox
= car_
->bbox( boxType
);
176 if( ! carbbox
->empty( ) )
178 typedef typeof *carbbox PathType
;
179 for( PathType::const_iterator i
= carbbox
->begin( ); i
!= carbbox
->end( ); ++i
)
181 Concrete::Length x
= (*i
)->mid_
->x_
;
182 xmin
= std::min( xmin
, x
);
183 xmax
= std::max( xmax
, x
);
185 Concrete::Length y
= (*i
)->mid_
->y_
;
186 ymin
= std::min( ymin
, y
);
187 ymax
= std::max( ymax
, y
);
192 return cdr_
->bboxAdd( boxType
, xmin
, ymin
, xmax
, ymax
);
196 Lang::GroupPair2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
198 /* Note the order! Objects are added on the car side of a group being built, so the car side is the "latter".
200 cdr_
->findTags( dst
, dyn
, key
, tf
);
201 car_
->findTags( dst
, dyn
, key
, tf
);
205 Lang::GroupPair2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
208 cdr_
->findOneTag( evalState
, key
, tf
) ||
209 car_
->findOneTag( evalState
, key
, tf
);
212 RefCountPtr
< const Lang::Group2D
>
213 Lang::GroupPair2D::removeShallow( Lang::Symbol::KeyType key
) const
216 typedef const Lang::Tagged2D TaggedType
;
217 TaggedType
* t
= dynamic_cast< TaggedType
* >( car_
.getPtr( ) );
218 if( t
!= 0 && t
->key( ) == key
)
220 return cdr_
->removeShallow( key
);
223 return RefCountPtr
< const Lang::Group2D
>( new Lang::GroupPair2D( car_
, cdr_
->removeShallow( key
), metaState_
) );
227 Lang::GroupPair2D::gcMark( Kernel::GCMarkedSet
& marked
)
229 const_cast< Lang::Drawable2D
* >( car_
.getPtr( ) )->gcMark( marked
);
230 const_cast< Lang::Group2D
* >( cdr_
.getPtr( ) )->gcMark( marked
);
234 Lang::GroupNull2D::GroupNull2D( )
237 Lang::GroupNull2D::~GroupNull2D( )
241 Lang::GroupNull2D::isNull( ) const
246 RefCountPtr
< const Lang::Group2D
>
247 Lang::GroupNull2D::removeShallow( Lang::Symbol::KeyType key
) const
249 return Lang::THE_NULL2D
;
253 Lang::GroupNull2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
256 RefCountPtr
< const Lang::ElementaryPath2D
>
257 Lang::GroupNull2D::bbox( Lang::Drawable2D::BoxType boxType
) const
259 return Lang::THE_EMPTYPATH2D
;
262 RefCountPtr
< const Lang::ElementaryPath2D
>
263 Lang::GroupNull2D::bboxAdd( Lang::Drawable2D::BoxType boxType
, Concrete::Length xmin
, Concrete::Length ymin
, Concrete::Length xmax
, Concrete::Length ymax
) const
265 Lang::ElementaryPath2D
* res
= new Lang::ElementaryPath2D
;
267 res
->push_back( new Concrete::PathPoint2D( xmin
, ymin
) );
268 res
->push_back( new Concrete::PathPoint2D( xmin
, ymax
) );
269 res
->push_back( new Concrete::PathPoint2D( xmax
, ymax
) );
270 res
->push_back( new Concrete::PathPoint2D( xmax
, ymin
) );
273 return RefCountPtr
< const Lang::ElementaryPath2D
>( res
);
277 Lang::XObject::XObject( const RefCountPtr
< SimplePDF::PDF_Object
> & resource
, const RefCountPtr
< const Lang::ElementaryPath2D
> & boundingbox
)
278 : metaState_( Kernel::THE_NO_STATE
), resource_( resource
), boundingbox_( boundingbox
), bleedbox_( boundingbox
)
281 Lang::XObject::XObject( const RefCountPtr
< SimplePDF::PDF_Object
> & resource
, const RefCountPtr
< const Lang::ElementaryPath2D
> & boundingbox
, const RefCountPtr
< const Lang::ElementaryPath2D
> & bleedbox
, const RefCountPtr
< const Kernel::GraphicsState
> & metaState
)
282 : metaState_( metaState
), resource_( resource
), boundingbox_( boundingbox
), bleedbox_( bleedbox
)
285 Lang::XObject::~XObject( )
289 Lang::XObject::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
291 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
, false );
292 if( ! tf
.isIdentity( ) )
296 os
<< " cm" << std::endl
;
298 if( metaState_
!= Kernel::THE_NO_STATE
)
300 pdfState
->graphics_
.synchForNonStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
302 os
<< pdfState
->resources_
->nameofXObject( resource_
) << " Do" << std::endl
;
305 RefCountPtr
< SimplePDF::PDF_Object
>
306 Lang::XObject::getResource( ) const
311 RefCountPtr
< const Lang::ElementaryPath2D
>
312 Lang::XObject::bbox( Lang::Drawable2D::BoxType boxType
) const
316 case Lang::Drawable2D::BOUNDING
:
318 case Lang::Drawable2D::BLEED
:
321 throw Exceptions::InternalError( "Lang::XObject::bbox: boxType out of range." );
324 RefCountPtr
< const Lang::XObject
>
325 Lang::XObject::cloneWithState( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
, Concrete::Length bleedMargin
) const
327 Concrete::Coords2D
llcorner( 0, 0 );
328 Concrete::Coords2D
urcorner( 0, 0 );
329 boundingbox_
->boundingRectangle( & llcorner
, & urcorner
);
331 Lang::ElementaryPath2D
* bleedBox
= new Lang::ElementaryPath2D
;
333 bleedBox
->push_back( new Concrete::PathPoint2D( llcorner
.x_
- bleedMargin
, llcorner
.y_
- bleedMargin
) );
334 bleedBox
->push_back( new Concrete::PathPoint2D( urcorner
.x_
+ bleedMargin
, llcorner
.y_
- bleedMargin
) );
335 bleedBox
->push_back( new Concrete::PathPoint2D( urcorner
.x_
+ bleedMargin
, urcorner
.y_
+ bleedMargin
) );
336 bleedBox
->push_back( new Concrete::PathPoint2D( llcorner
.x_
- bleedMargin
, urcorner
.y_
+ bleedMargin
) );
339 return RefCountPtr
< const Lang::XObject
>( new Lang::XObject( resource_
, boundingbox_
, RefCountPtr
< const Lang::ElementaryPath2D
>( bleedBox
), metaState
) );
343 Lang::XObject::setDebugStr( const std::string
& debugStr
)
345 debugStr_
= debugStr
;
349 Lang::XObject::getDebugStr( ) const
355 Lang::XObject::show( std::ostream
& os
) const
357 os
<< "XObject (" << getDebugStr( ) << ")" ;
361 Lang::XObject::gcMark( Kernel::GCMarkedSet
& marked
)
363 // At the time of writing, there is nothing to propagate to.
367 Lang::TransparencyGroup::TransparencyGroup( const RefCountPtr
< SimplePDF::PDF_Indirect_out
> & indirection
, RefCountPtr
< const Lang::ElementaryPath2D
> mybbox
, const RefCountPtr
< const Lang::ColorSpace
> & colorSpace
)
368 : Lang::XObject( indirection
, mybbox
), colorSpace_( colorSpace
), indirection_( indirection
)
371 Lang::TransparencyGroup::~TransparencyGroup( )
374 RefCountPtr
< const Lang::ColorSpace
>
375 Lang::TransparencyGroup::colorSpace( ) const
380 RefCountPtr
< SimplePDF::PDF_Indirect_out
>
381 Lang::TransparencyGroup::getPDF_Object( ) const
383 return indirection_
.unconst_cast
< SimplePDF::PDF_Indirect_out
>( );
386 RefCountPtr
< const Lang::TransparencyGroup
>
387 Helpers::newTransparencyGroup( const RefCountPtr
< const Lang::Drawable2D
> & content
, bool isolated
, bool knockout
, const RefCountPtr
< const Lang::ColorSpace
> & blendSpace
)
389 RefCountPtr
< const Lang::ElementaryPath2D
> theBBox
= content
->bbox( Lang::Drawable2D::BOUNDING
);
390 Concrete::Coords2D
llcorner( 0, 0 );
391 Concrete::Coords2D
urcorner( 0, 0 );
392 if( ! theBBox
->boundingRectangle( & llcorner
, & urcorner
) )
394 throw Exceptions::InternalError( "newTransparencyGroup: The object has no bounding box!" );
397 using namespace Shapes
;
399 RefCountPtr
< SimplePDF::PDF_Stream_out
> form
;
401 (*form
)[ "Subtype" ] = SimplePDF::newName( "Form" );
402 (*form
)[ "FormType" ] = SimplePDF::newInt( 1 );
403 (*form
)[ "BBox" ] = RefCountPtr
< SimplePDF::PDF_Vector
>( new SimplePDF::PDF_Vector( llcorner
.x_
.offtype
< 1, 0 >( ), llcorner
.y_
.offtype
< 1, 0 >( ),
404 urcorner
.x_
.offtype
< 1, 0 >( ), urcorner
.y_
.offtype
< 1, 0 >( ) ) );
405 RefCountPtr
< SimplePDF::PDF_Resources
> resources
;
406 (*form
)[ "Resources" ] = SimplePDF::indirect( resources
, & Kernel::theIndirectObjectCount
);
408 if( ! Kernel::allowTransparency
)
412 else if( ! Kernel::the_PDF_version
.greaterOrEqual( SimplePDF::PDF_Version::PDF_1_4
) )
414 Kernel::the_PDF_version
.message( SimplePDF::PDF_Version::PDF_1_4
, "A transparency group was replaced by a plain XObject." );
418 RefCountPtr
< SimplePDF::PDF_Dictionary
> groupDic
;
419 (*form
)[ "Group" ] = groupDic
;
420 (*groupDic
)[ "S" ] = SimplePDF::newName( "Transparency" );
421 if( ! blendSpace
->isInherent( ) )
423 (*groupDic
)[ "CS" ] = blendSpace
->name( );
427 (*groupDic
)[ "I" ] = SimplePDF::newBoolean( true );
431 (*groupDic
)[ "K" ] = SimplePDF::newBoolean( true );
435 /* There's a possibility of adding a transformation matrix entry in the dictionary here, but it is not used, not even
436 * for transformed drawables.
438 // (*markForm)[ "Matrix" ] = RefCountPtr<PDF_Object>( new PDF_Vector( 1, 0, 0, 1, -30, -30 ) );
440 Kernel::PageContentStates
pdfState( resources
);
441 content
->shipout( form
->data
, & pdfState
, Lang::Transform2D( 1, 0, 0, 1, Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
) );
443 Lang::TransparencyGroup
* res
= new Lang::TransparencyGroup( SimplePDF::indirect( form
, & Kernel::theIndirectObjectCount
),
444 content
->bbox( Lang::Drawable2D::BOUNDING
),
446 res
->setDebugStr( "transparency group" );
447 return RefCountPtr
< const Lang::TransparencyGroup
>( res
);
451 Lang::RasterImage::newInstance( size_t size_x
, size_t size_y
, size_t size_depth
, Concrete::Length pixelSize_x
, Concrete::Length pixelSize_y
, RefCountPtr
< const Lang::ColorSpace
> colorSpace
)
453 RefCountPtr
< SimplePDF::PDF_Stream_out
> stream
= RefCountPtr
< SimplePDF::PDF_Stream_out
>( new SimplePDF::PDF_Stream_out
);
454 RefCountPtr
< SimplePDF::PDF_Object
> indirection
= SimplePDF::indirect( stream
, & Kernel::theIndirectObjectCount
);
456 (*stream
)[ "Subtype" ] = SimplePDF::newName( "Image" );
457 (*stream
)[ "Width" ] = SimplePDF::newInt( size_x
);
458 (*stream
)[ "Height" ] = SimplePDF::newInt( size_y
);
459 (*stream
)[ "ColorSpace" ] = colorSpace
->name( );
460 (*stream
)[ "BitsPerComponent" ] = SimplePDF::newInt( size_depth
);
462 return new RasterImage( indirection
, size_x
, size_y
, size_depth
, pixelSize_x
, pixelSize_y
, colorSpace
, stream
);
466 Lang::RasterImage::setSoftMask( const RefCountPtr
< const Lang::RasterImage
> & softMask
)
468 /* The caller is responsible for also adding the soft mask under "SMask" in the stream dictionary! */
469 softMask_
= softMask
;
472 Lang::RasterImage::RasterImage( const RefCountPtr
< SimplePDF::PDF_Object
> & resource
, size_t size_x
, size_t size_y
, size_t size_depth
, Concrete::Length pixelSize_x
, Concrete::Length pixelSize_y
, RefCountPtr
< const Lang::ColorSpace
> colorSpace
, RefCountPtr
< SimplePDF::PDF_Stream_out
> & stream
)
473 : Lang::XObject( resource
, RefCountPtr
< const Lang::ElementaryPath2D
>( newBoundingBox( size_x
, size_y
, pixelSize_x
, pixelSize_y
) ) ),
474 size_x_( size_x
), size_y_( size_y
), size_depth_( size_depth
), pixelSize_x_( pixelSize_x
), pixelSize_y_( pixelSize_y
), colorSpace_( colorSpace
),
475 softMask_( NullPtr
< const Lang::RasterImage
>( ) ),
479 Lang::ElementaryPath2D
*
480 Lang::RasterImage::newBoundingBox( size_t size_x
, size_t size_y
, Concrete::Length pixelSize_x
, Concrete::Length pixelSize_y
)
482 /* Note that this bounding box assumes that the image is scaled to resolution during shipout. */
483 Lang::ElementaryPath2D
* res
= new Lang::ElementaryPath2D
;
485 res
->push_back( new Concrete::PathPoint2D( Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
) );
486 res
->push_back( new Concrete::PathPoint2D( size_x
* pixelSize_x
, Concrete::ZERO_LENGTH
) );
487 res
->push_back( new Concrete::PathPoint2D( size_x
* pixelSize_x
, size_y
* pixelSize_y
) );
488 res
->push_back( new Concrete::PathPoint2D( Concrete::ZERO_LENGTH
, size_y
* pixelSize_y
) );
493 Lang::RasterImage::~RasterImage( )
496 RefCountPtr
< const Lang::Class
> Lang::RasterImage::TypeID( new Lang::SystemFinalClass( strrefdup( "RasterImage" ) ) );
497 TYPEINFOIMPL( RasterImage
);
500 Lang::RasterImage::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
502 Lang::XObject::shipout( os
, pdfState
, Lang::Transform2D( tf
, Transform2D( size_x_
* static_cast< double >( Concrete::Length::offtype( pixelSize_x_
) ), 0, 0, size_y_
* static_cast< double >( Concrete::Length::offtype( pixelSize_y_
) ),
503 Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
) ) );
506 Kernel::VariableHandle
507 Lang::RasterImage::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
509 if( strcmp( fieldID
, "size_x" ) == 0 )
511 return Helpers::newValHandle( new Lang::Integer( size_x_
) );
513 if( strcmp( fieldID
, "size_y" ) == 0 )
515 return Helpers::newValHandle( new Lang::Integer( size_y_
) );
517 if( strcmp( fieldID
, "depth" ) == 0 )
519 return Helpers::newValHandle( new Lang::Integer( size_depth_
) );
521 if( strcmp( fieldID
, "space" ) == 0 )
523 return Kernel::VariableHandle( new Kernel::Variable( colorSpace_
) );
525 throw Exceptions::NonExistentMember( getTypeName( ), fieldID
);
529 Lang::RasterImage::gcMark( Kernel::GCMarkedSet
& marked
)
531 const_cast< Lang::ColorSpace
* >( colorSpace_
.getPtr( ) )->gcMark( marked
);
532 if( softMask_
!= NullPtr
< const Lang::RasterImage
>( ) )
534 const_cast< Lang::RasterImage
* >( softMask_
.getPtr( ) )->gcMark( marked
);
536 Lang::XObject::gcMark( marked
);
541 Lang::PaintedPath2D::PaintedPath2D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
,
542 const char * paintCmd
)
543 : metaState_( metaState
), paintCmd_( paintCmd
)
546 Lang::PaintedPath2D::PaintedPath2D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
,
547 RefCountPtr
< const Lang::ElementaryPath2D
> path
,
548 const char * paintCmd
)
549 : metaState_( metaState
), paintCmd_( paintCmd
)
554 Lang::PaintedPath2D::PaintedPath2D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
,
555 RefCountPtr
< const Lang::MultiPath2D
> paths
,
556 const char * paintCmd
)
557 : metaState_( metaState
), paintCmd_( paintCmd
)
559 for( Lang::MultiPath2D::const_iterator i
= paths
->begin( ); i
!= paths
->end( ); ++i
)
562 typedef const Lang::ElementaryPath2D ArgType
;
563 RefCountPtr
< ArgType
> subpath
= (*i
).down_cast
< ArgType
>( );
564 if( subpath
!= NullPtr
< ArgType
>( ) )
566 addSubPath( subpath
);
572 typedef const Lang::CompositePath2D ArgType
;
573 ArgType
* subpath
= dynamic_cast< ArgType
* >( (*i
).getPtr( ) );
576 addSubPath( subpath
->getElementaryPath( ) );
580 throw Exceptions::InternalError( "Painting 2D path: Encountered a subpath of unexpected type" );
584 Lang::PaintedPath2D::~PaintedPath2D( )
587 RefCountPtr
< const Lang::Class
> Lang::PaintedPath2D::TypeID( new Lang::SystemFinalClass( strrefdup( "PaintedPath2D" ) ) );
588 TYPEINFOIMPL( PaintedPath2D
);
591 Lang::PaintedPath2D::addSubPath( RefCountPtr
< const Lang::ElementaryPath2D
> subpath
)
593 path_
.push_back( subpath
);
597 Lang::PaintedPath2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
599 /* Transforming the path by tf is not good enough, since that does not transform softmasks etc.
603 strcpy( pdfCmd
, paintCmd_
);
605 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
, false );
606 if( ! tf
.isIdentity( ) )
610 os
<< " cm" << std::endl
;
612 if( strcmp( paintCmd_
, "S" ) == 0 )
614 pdfState
->graphics_
.synchForStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
616 else if( strcmp( paintCmd_
, "f" ) == 0 ||
617 strcmp( paintCmd_
, "f*" ) == 0 )
619 pdfState
->graphics_
.synchForNonStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
621 else if( strcmp( paintCmd_
, "B" ) == 0 ||
622 strcmp( paintCmd_
, "B*" ) == 0 ||
623 strcmp( paintCmd_
, "b" ) == 0 ||
624 strcmp( paintCmd_
, "b*" ) == 0 )
626 pdfState
->graphics_
.synchForNonStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
627 pdfState
->graphics_
.synchForStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
629 else if( strcmp( paintCmd_
, "E" ) == 0 ||
630 strcmp( paintCmd_
, "E*" ) == 0 ||
631 strcmp( paintCmd_
, "e" ) == 0 ||
632 strcmp( paintCmd_
, "e*" ) == 0 )
634 pdfCmd
[0] += 'B' - 'E';
635 // Note that this is my own interpretation; usually, the stroke is made with the stroking color,
636 // but I use this to make filled regions just a little bit bigger, and then it is the nonstroking
637 // color that shall be applied to the stroke as well.
638 pdfState
->graphics_
.synchForNonStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
639 pdfState
->graphics_
.synchStrokingColorWithNonStrokingColor( os
, pdfState
->resources_
.getPtr( ), Concrete::ZERO_LENGTH
);
643 throw Exceptions::InternalError( "Unexpected paintCmd in PaintedPath2D::shipout" );
646 typedef typeof path_ ListType
;
647 for( ListType::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
649 (*i
)->writePath( os
);
651 os
<< " " << pdfCmd
<< std::endl
;
654 RefCountPtr
< const Lang::ElementaryPath2D
>
655 Lang::PaintedPath2D::bbox( Lang::Drawable2D::BoxType boxType
) const
659 return RefCountPtr
< const Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D
);
662 Concrete::Length xmin
= Concrete::HUGE_LENGTH
;
663 Concrete::Length xmax
= -Concrete::HUGE_LENGTH
;
664 Concrete::Length ymin
= Concrete::HUGE_LENGTH
;
665 Concrete::Length ymax
= -Concrete::HUGE_LENGTH
;
667 Concrete::Coords2D
llcorner( 0, 0 ); /* Temporary variables to be used in the loop below. */
668 Concrete::Coords2D
urcorner( 0, 0 );
670 typedef typeof path_ PathType
;
671 for( PathType::const_iterator j
= path_
.begin( ); j
!= path_
.end( ); ++j
)
673 if( (*j
)->boundingRectangle( & llcorner
, & urcorner
) )
676 xmin
= std::min( xmin
, llcorner
.x_
);
677 xmax
= std::max( xmax
, urcorner
.x_
);
678 ymin
= std::min( ymin
, llcorner
.y_
);
679 ymax
= std::max( ymax
, urcorner
.y_
);
683 Lang::ElementaryPath2D
* res
= new Lang::ElementaryPath2D
;
685 if( xmin
< Concrete::HUGE_LENGTH
)
687 if( toupper( *paintCmd_
) == 'S' ||
688 toupper( *paintCmd_
) == 'B' )
690 xmin
-= 0.5 * metaState_
->width_
;
691 ymin
-= 0.5 * metaState_
->width_
;
692 xmax
+= 0.5 * metaState_
->width_
;
693 ymax
+= 0.5 * metaState_
->width_
;
695 res
->push_back( new Concrete::PathPoint2D( xmin
, ymin
) );
696 res
->push_back( new Concrete::PathPoint2D( xmin
, ymax
) );
697 res
->push_back( new Concrete::PathPoint2D( xmax
, ymax
) );
698 res
->push_back( new Concrete::PathPoint2D( xmax
, ymin
) );
702 return RefCountPtr
< const Lang::ElementaryPath2D
>( res
);
706 Lang::PaintedPath2D::gcMark( Kernel::GCMarkedSet
& marked
)
710 Lang::Transformed2D::Transformed2D( RefCountPtr
< const Lang::Drawable2D
> element
, const Lang::Transform2D
& mytf
)
711 : mytf_( mytf
), element_( element
)
714 Lang::Transformed2D::~Transformed2D( )
718 Lang::Transformed2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
720 element_
->shipout( os
, pdfState
, Lang::Transform2D( tf
, mytf_
) );
723 RefCountPtr
< const Lang::ElementaryPath2D
>
724 Lang::Transformed2D::bbox( Lang::Drawable2D::BoxType boxType
) const
726 return element_
->bbox( boxType
)->elementaryTransformed( mytf_
);
730 Lang::Transformed2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
732 element_
->findTags( dst
, dyn
, key
, Lang::Transform2D( tf
, mytf_
) );
736 Lang::Transformed2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
739 element_
->findOneTag( evalState
, key
, Lang::Transform2D( tf
, mytf_
) );
743 Lang::Transformed2D::gcMark( Kernel::GCMarkedSet
& marked
)
745 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
749 Lang::BBoxed2D::BBoxed2D( RefCountPtr
< const Lang::Drawable2D
> element
, RefCountPtr
< const Lang::ElementaryPath2D
> mybbox
, BoxType boxType
)
750 : Lang::PaintedPolygon2D( Kernel::THE_NO_STATE
, mybbox
), mybbox_( mybbox
), element_( element
), boxType_( boxType
)
753 Lang::BBoxed2D::~BBoxed2D( )
757 Lang::BBoxed2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
759 /* At the moment, we don't clip according to the bbox, we only lie about our size.
761 element_
->shipout( os
, pdfState
, tf
);
764 RefCountPtr
< const Lang::ElementaryPath2D
>
765 Lang::BBoxed2D::bbox( Lang::Drawable2D::BoxType boxType
) const
768 || ( boxType
== Lang::Drawable2D::BOUNDING
&& boxType_
== BOUNDING
)
769 || ( boxType
== Lang::Drawable2D::BLEED
&& boxType_
== BLEED
) )
773 return element_
->bbox( boxType
);
777 Lang::BBoxed2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
779 element_
->findTags( dst
, dyn
, key
, tf
);
783 Lang::BBoxed2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
786 element_
->findOneTag( evalState
, key
, tf
);
790 Lang::BBoxed2D::gcMark( Kernel::GCMarkedSet
& marked
)
792 Lang::PaintedPolygon2D::gcMark( marked
);
793 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
797 Lang::Clipped2D::Clipped2D( const RefCountPtr
< const Lang::Drawable2D
> & element
, const char * clipCommand
)
798 : element_( element
), clipCommand_( clipCommand
)
801 Lang::Clipped2D::~Clipped2D( )
805 Lang::Clipped2D::addSubPath( const RefCountPtr
< const Lang::ElementaryPath2D
> & subpath
)
807 clipList_
.push_back( subpath
);
811 Lang::Clipped2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
813 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
);
814 if( ! tf
.isIdentity( ) )
817 os
<< " cm" << std::endl
;
819 typedef typeof clipList_ ListType
;
820 for( ListType::const_iterator i
= clipList_
.begin( ); i
!= clipList_
.end( ); ++i
)
822 (*i
)->writePath( os
);
824 os
<< " " << clipCommand_
<< " n" << std::endl
;
825 element_
->shipout( os
, pdfState
, THE_2D_IDENTITY
);
828 RefCountPtr
< const Lang::ElementaryPath2D
>
829 Lang::Clipped2D::bbox( Lang::Drawable2D::BoxType boxType
) const
831 RefCountPtr
< const Lang::ElementaryPath2D
> elem_bbox
= element_
->bbox( boxType
);
833 if( clipList_
.empty( ) )
835 return RefCountPtr
< const Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D
);
838 Concrete::Coords2D
llElemBbox( 0, 0 );
839 Concrete::Coords2D
urElemBbox( 0, 0 );
840 elem_bbox
->boundingRectangle( & llElemBbox
, & urElemBbox
);
842 Concrete::Length xmin
= Concrete::HUGE_LENGTH
;
843 Concrete::Length xmax
= -Concrete::HUGE_LENGTH
;
844 Concrete::Length ymin
= Concrete::HUGE_LENGTH
;
845 Concrete::Length ymax
= -Concrete::HUGE_LENGTH
;
847 Concrete::Coords2D
llcorner( 0, 0 ); /* Temporary variables to be used in the loop below. */
848 Concrete::Coords2D
urcorner( 0, 0 );
850 typedef typeof clipList_ PathType
;
851 for( PathType::const_iterator j
= clipList_
.begin( ); j
!= clipList_
.end( ); ++j
)
853 if( (*j
)->boundingRectangle( & llcorner
, & urcorner
) )
856 xmin
= std::min( xmin
, llcorner
.x_
);
857 xmax
= std::max( xmax
, urcorner
.x_
);
858 ymin
= std::min( ymin
, llcorner
.y_
);
859 ymax
= std::max( ymax
, urcorner
.y_
);
863 xmin
= std::max( xmin
, llElemBbox
.x_
);
864 ymin
= std::max( ymin
, llElemBbox
.y_
);
865 xmax
= std::min( xmax
, urElemBbox
.x_
);
866 ymax
= std::min( ymax
, urElemBbox
.y_
);
868 Lang::ElementaryPath2D
* res
= new Lang::ElementaryPath2D
;
870 if( xmin
< xmax
&& ymin
< ymax
)
872 res
->push_back( new Concrete::PathPoint2D( xmin
, ymin
) );
873 res
->push_back( new Concrete::PathPoint2D( xmin
, ymax
) );
874 res
->push_back( new Concrete::PathPoint2D( xmax
, ymax
) );
875 res
->push_back( new Concrete::PathPoint2D( xmax
, ymin
) );
879 return RefCountPtr
< const Lang::ElementaryPath2D
>( res
);
883 Lang::Clipped2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
885 element_
->findTags( dst
, dyn
, key
, tf
);
889 Lang::Clipped2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
892 element_
->findOneTag( evalState
, key
, tf
);
896 Lang::Clipped2D::gcMark( Kernel::GCMarkedSet
& marked
)
898 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
901 RefCountPtr
< const Lang::Drawable2D
>
902 Lang::Clipped2D::debugPolys( ) const
904 Kernel::GraphicsState
* frameStatePtr
= new Kernel::GraphicsState( true );
905 frameStatePtr
->width_
= Concrete::Length( 0.2 );
906 RefCountPtr
< const Kernel::GraphicsState
> frameState( frameStatePtr
);
908 Lang::PaintedPath2D
* res
= new Lang::PaintedPath2D( frameState
, "S" );
909 typedef typeof clipList_ ListType
;
910 for( ListType::const_iterator i
= clipList_
.begin( ); i
!= clipList_
.end( ); ++i
)
912 res
->addSubPath( *i
);
915 return RefCountPtr
< const Lang::Drawable2D
>( res
);
919 Lang::Clipped2D::isSingleConvexPoly( Concrete::Length tol
) const
921 if( clipList_
.size( ) != 1 )
925 return clipList_
.front( )->isConvexPoly( tol
);
929 Lang::Clipped2D::convexPolyContains( const Concrete::Coords2D
& p
, Concrete::Length tol
) const
931 return clipList_
.front( )->convexPolyContains( p
, tol
);
934 Lang::SoftMasked2D::SoftMasked2D( const RefCountPtr
< const Lang::Drawable2D
> & element
, const RefCountPtr
< const Lang::SoftMask
> & mask
)
935 : element_( element
), mask_( mask
)
938 Lang::SoftMasked2D::~SoftMasked2D( )
942 Lang::SoftMasked2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
944 const SimplePDF::PDF_Version::Version SOFTMASK_VERSION
= SimplePDF::PDF_Version::PDF_1_4
;
945 if( Kernel::the_PDF_version
.greaterOrEqual( SOFTMASK_VERSION
) )
947 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
);
948 if( ! tf
.isIdentity( ) )
951 os
<< " cm" << std::endl
;
953 os
<< pdfState
->resources_
->nameofGraphicsState( mask_
->graphicsStateResource_
) << " gs " << std::endl
;
954 element_
->shipout( os
, pdfState
, THE_2D_IDENTITY
);
958 Kernel::the_PDF_version
.message( SOFTMASK_VERSION
, "A soft mask was ignored." );
959 element_
->shipout( os
, pdfState
, tf
);
963 RefCountPtr
< const Lang::ElementaryPath2D
>
964 Lang::SoftMasked2D::bbox( Lang::Drawable2D::BoxType boxType
) const
966 return element_
->bbox( boxType
);
970 Lang::SoftMasked2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
972 element_
->findTags( dst
, dyn
, key
, tf
);
976 Lang::SoftMasked2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
979 element_
->findOneTag( evalState
, key
, tf
);
983 Lang::SoftMasked2D::gcMark( Kernel::GCMarkedSet
& marked
)
985 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
986 const_cast< Lang::SoftMask
* >( mask_
.getPtr( ) )->gcMark( marked
);
990 Lang::TextMasked2D::TextMasked2D( const RefCountPtr
< const Lang::Drawable2D
> & element
, const RefCountPtr
< const Lang::Text
> & mask
)
991 : element_( element
), mask_( mask
)
994 Lang::TextMasked2D::~TextMasked2D( )
998 Lang::TextMasked2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
1000 mask_
->shipout_clip( os
, pdfState
, tf
, element_
);
1003 RefCountPtr
< const Lang::ElementaryPath2D
>
1004 Lang::TextMasked2D::bbox( Lang::Drawable2D::BoxType boxType
) const
1006 return mask_
->bbox( boxType
);
1010 Lang::TextMasked2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
1012 element_
->findTags( dst
, dyn
, key
, tf
);
1016 Lang::TextMasked2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
1019 element_
->findOneTag( evalState
, key
, tf
);
1023 Lang::TextMasked2D::gcMark( Kernel::GCMarkedSet
& marked
)
1025 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
1026 const_cast< Lang::Text
* >( mask_
.getPtr( ) )->gcMark( marked
);
1030 Lang::Drawable3D::Drawable3D( )
1033 Lang::Drawable3D::~Drawable3D( )
1036 RefCountPtr
< const Lang::Transformed3D
>
1037 Lang::Drawable3D::typed_transformed( const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1039 return RefCountPtr
< const Lang::Transformed3D
>( new Lang::Transformed3D( self
, tf
) );
1042 RefCountPtr
< const Lang::Geometric3D
>
1043 Lang::Drawable3D::transformed( const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Geometric3D
> & self
) const
1045 return typed_transformed( tf
, self
.down_cast
< const Lang::Drawable3D
>( ) );
1048 RefCountPtr
< const Lang::Geometric2D
>
1049 Lang::Drawable3D::to2D( const Kernel::PassedDyn
& dyn
, const RefCountPtr
< const Lang::Geometric3D
> & self
) const
1051 typedef const Lang::Drawable3D SelfType
;
1052 RefCountPtr
< SelfType
> typedSelf
= self
.down_cast
< SelfType
>( );
1053 if( typedSelf
== NullPtr
< SelfType
>( ) )
1055 throw Exceptions::InternalError( "The self-value passed to Drawable3D::to2D was of bad type." );
1057 return typed_to2D( dyn
, Lang::THE_3D_IDENTITY
, typedSelf
);
1061 Lang::Drawable3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1063 // Not overloading this methods means that there are no tagged objects within this.
1067 Lang::Drawable3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1069 // Not overloading this methods means that there are no tagged objects within this.
1074 Lang::Drawable3D::gcMark( Kernel::GCMarkedSet
& marked
)
1077 RefCountPtr
< const Lang::Class
> Lang::Drawable3D::TypeID
= NullPtr
< const Lang::Class
>( ); /* The value is set in main */
1078 TYPEINFOIMPL( Drawable3D
);
1079 DISPATCHIMPL( Drawable3D
);
1082 Lang::Group3D::Group3D( )
1085 Lang::Group3D::~Group3D( )
1088 RefCountPtr
< const Lang::Drawable2D
>
1089 Lang::Group3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1091 return group_to2D( dyn
, tf
);
1095 RefCountPtr
< const Lang::Class
> Lang::Group3D::TypeID( new Lang::SystemFinalClass( strrefdup( "Group3D" ) ) );
1096 TYPEINFOIMPL( Group3D
);
1098 RefCountPtr
< const Lang::Group3D
>
1099 Helpers::newGroup3D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
, const RefCountPtr
< const Lang::Drawable3D
> & obj2
, const RefCountPtr
< const Lang::Drawable3D
> & obj1
)
1101 RefCountPtr
< const Lang::Group3D
> res
= Lang::THE_NULL3D
;
1102 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj1
,
1105 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj2
,
1111 RefCountPtr
< const Lang::Group3D
>
1112 Helpers::newGroup3D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
, const RefCountPtr
< const Lang::Drawable3D
> & obj3
, const RefCountPtr
< const Lang::Drawable3D
> & obj2
, const RefCountPtr
< const Lang::Drawable3D
> & obj1
)
1114 RefCountPtr
< const Lang::Group3D
> res
= Lang::THE_NULL3D
;
1115 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj1
,
1118 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj2
,
1121 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj3
,
1128 Lang::GroupPair3D::GroupPair3D( const RefCountPtr
< const Lang::Drawable3D
> & car
, const RefCountPtr
< const Lang::Group3D
> & cdr
, const RefCountPtr
< const Kernel::GraphicsState
> & metaState
)
1129 : metaState_( metaState
), car_( car
), cdr_( cdr
)
1132 Lang::GroupPair3D::~GroupPair3D( )
1136 Lang::GroupPair3D::isNull( ) const
1141 RefCountPtr
< const Lang::Group2D
>
1142 Lang::GroupPair3D::group_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
) const
1144 return RefCountPtr
< const Lang::Group2D
>( new Lang::GroupPair2D( car_
->typed_to2D( dyn
, tf
, car_
),
1145 cdr_
->group_to2D( dyn
, tf
),
1150 Lang::GroupPair3D::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1152 car_
->polygonize( zBufPile
, linePile
, dyn
, tf
, car_
);
1153 cdr_
->polygonize( zBufPile
, linePile
, dyn
, tf
, cdr_
);
1157 Lang::GroupPair3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1159 /* See note on order in GroupPair2D!
1161 cdr_
->findTags( dst
, dyn
, key
, tf
);
1162 car_
->findTags( dst
, dyn
, key
, tf
);
1166 Lang::GroupPair3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1169 cdr_
->findOneTag( evalState
, key
, tf
) ||
1170 car_
->findOneTag( evalState
, key
, tf
);
1173 RefCountPtr
< const Lang::Group3D
>
1174 Lang::GroupPair3D::removeShallow( Lang::Symbol::KeyType key
) const
1177 typedef const Lang::Tagged3D TaggedType
;
1178 TaggedType
* t
= dynamic_cast< TaggedType
* >( car_
.getPtr( ) );
1179 if( t
!= 0 && t
->key( ) == key
)
1181 return cdr_
->removeShallow( key
);
1184 return RefCountPtr
< const Lang::Group3D
>( new Lang::GroupPair3D( car_
, cdr_
->removeShallow( key
), metaState_
) );
1188 Lang::GroupPair3D::gcMark( Kernel::GCMarkedSet
& marked
)
1190 const_cast< Lang::Drawable3D
* >( car_
.getPtr( ) )->gcMark( marked
);
1191 const_cast< Lang::Group3D
* >( cdr_
.getPtr( ) )->gcMark( marked
);
1195 Lang::GroupNull3D::GroupNull3D( )
1198 Lang::GroupNull3D::~GroupNull3D( )
1202 Lang::GroupNull3D::isNull( ) const
1207 RefCountPtr
< const Lang::Group3D
>
1208 Lang::GroupNull3D::removeShallow( Lang::Symbol::KeyType key
) const
1210 return Lang::THE_NULL3D
;
1213 RefCountPtr
< const Lang::Group2D
>
1214 Lang::GroupNull3D::group_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
) const
1216 return Lang::THE_NULL2D
;
1220 Lang::GroupNull3D::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1224 Lang::Drawable2Din3D::Drawable2Din3D( RefCountPtr
< const Lang::Drawable2D
> element
)
1225 : element_( element
)
1228 Lang::Drawable2Din3D::~Drawable2Din3D( )
1231 RefCountPtr
< const Lang::Drawable2D
>
1232 Lang::Drawable2Din3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1234 Concrete::Length eyez
= dyn
->getEyeZ( );
1235 if( eyez
< Concrete::HUGE_LENGTH
)
1237 std::ostringstream msg
;
1238 msg
<< "An object of type " << element_
->getTypeName( ) << " in 3D cannot go back to 2D viewed from a finite distance. Consider using facing rather than immerse." ;
1239 throw Exceptions::MiscellaneousRequirement( strrefdup( msg
.str( ).c_str( ) ) );
1242 // The transform in 2D is obtained by setting z = 0 in the source 3D coordinates, and omitting the z-coordinate in the new coordinates
1244 return RefCountPtr
< const Lang::Drawable2D
>( new Lang::Transformed2D( element_
, Lang::Transform2D( tf
.xx_
, tf
.yx_
, tf
.xy_
, tf
.yy_
, tf
.xt_
, tf
.yt_
) ) );
1248 Lang::Drawable2Din3D::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1250 throw Exceptions::NotImplemented( "Triangularization of immersed objects." );
1254 Lang::Drawable2Din3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1256 Concrete::Length eyez
= dyn
->getEyeZ( );
1257 if( eyez
< Concrete::HUGE_LENGTH
)
1259 std::ostringstream msg
;
1260 msg
<< "Tags in an immersed object are not accessible from a finite viewing distance. Consider using facing rather than immerse." ;
1261 throw Exceptions::MiscellaneousRequirement( strrefdup( msg
.str( ).c_str( ) ) );
1264 // The transform in 2D is obtained by setting z = 0 in the source 3D coordinates, and omitting the z-coordinate in the new coordinates
1266 element_
->findTags( dst
, dyn
, key
, Lang::Transform2D( tf
.xx_
, tf
.yx_
, tf
.xy_
, tf
.yy_
, tf
.xt_
, tf
.yt_
) );
1270 Lang::Drawable2Din3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1272 Concrete::Length eyez
= evalState
->dyn_
->getEyeZ( );
1273 if( eyez
< Concrete::HUGE_LENGTH
)
1275 std::ostringstream msg
;
1276 msg
<< "Tags in an immersed object are not accessible from a finite viewing distance. Consider using facing rather than immerse." ;
1277 throw Exceptions::MiscellaneousRequirement( strrefdup( msg
.str( ).c_str( ) ) );
1280 // The transform in 2D is obtained by setting z = 0 in the source 3D coordinates, and omitting the z-coordinate in the new coordinates
1283 element_
->findOneTag( evalState
, key
, Lang::Transform2D( tf
.xx_
, tf
.yx_
, tf
.xy_
, tf
.yy_
, tf
.xt_
, tf
.yt_
) );
1287 Lang::Drawable2Din3D::gcMark( Kernel::GCMarkedSet
& marked
)
1289 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
1294 Lang::Facing2Din3D::Facing2Din3D( RefCountPtr
< const Lang::Drawable2D
> element
, bool scale
, bool distort
)
1295 : element_( element
), scale_( scale
), distort_( distort
)
1298 Lang::Facing2Din3D::~Facing2Din3D( )
1301 RefCountPtr
< const Lang::Drawable2D
>
1302 Lang::Facing2Din3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1304 Concrete::Length eyez
= dyn
->getEyeZ( );
1306 if( scale_
&& eyez
< Concrete::HUGE_LENGTH
)
1308 s
= eyez
/ ( eyez
- tf
.zt_
);
1313 if( eyez
< Concrete::HUGE_LENGTH
)
1315 x
= tf
.xt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1316 y
= tf
.yt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1326 return RefCountPtr
< const Lang::Drawable2D
>( new Lang::Transformed2D( element_
, Lang::Transform2D( s
* tf
.xx_
, s
* tf
.yx_
, s
* tf
.xy_
, s
* tf
.yy_
, x
, y
) ) );
1330 return RefCountPtr
< const Lang::Drawable2D
>( new Lang::Transformed2D( element_
, Lang::Transform2D( s
, 0, 0, s
, x
, y
) ) );
1335 Lang::Facing2Din3D::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1337 throw Exceptions::MiscellaneousRequirement( "Facing objects cannot be polygonized." );
1341 Lang::Facing2Din3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1343 Concrete::Length eyez
= dyn
->getEyeZ( );
1345 if( scale_
&& eyez
< Concrete::HUGE_LENGTH
)
1347 s
= eyez
/ ( eyez
- tf
.zt_
);
1352 if( eyez
< Concrete::HUGE_LENGTH
)
1354 x
= tf
.xt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1355 y
= tf
.yt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1365 element_
->findTags( dst
, dyn
, key
, Lang::Transform2D( s
* tf
.xx_
, s
* tf
.yx_
, s
* tf
.xy_
, s
* tf
.yy_
, x
, y
) );
1369 element_
->findTags( dst
, dyn
, key
, Lang::Transform2D( s
, 0, 0, s
, x
, y
) );
1374 Lang::Facing2Din3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1376 Concrete::Length eyez
= evalState
->dyn_
->getEyeZ( );
1378 if( scale_
&& eyez
< Concrete::HUGE_LENGTH
)
1380 s
= eyez
/ ( eyez
- tf
.zt_
);
1385 if( eyez
< Concrete::HUGE_LENGTH
)
1387 x
= tf
.xt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1388 y
= tf
.yt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1399 element_
->findOneTag( evalState
, key
, Lang::Transform2D( s
* tf
.xx_
, s
* tf
.yx_
, s
* tf
.xy_
, s
* tf
.yy_
, x
, y
) );
1404 element_
->findOneTag( evalState
, key
, Lang::Transform2D( s
, 0, 0, s
, x
, y
) );
1409 Lang::Facing2Din3D::gcMark( Kernel::GCMarkedSet
& marked
)
1411 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
1415 Lang::FacingFunction3D::FacingFunction3D( Kernel::PassedDyn dyn
, RefCountPtr
< const Lang::Function
> generator
)
1416 : dyn_( dyn
), generator_( generator
)
1419 Lang::FacingFunction3D::~FacingFunction3D( )
1422 RefCountPtr
< const Lang::Drawable2D
>
1423 Lang::FacingFunction3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1425 /* Too bad we can't call the function CPP here...
1427 Kernel::ValueRef valUntyped
= NullPtr
< const Lang::Value
>( );
1429 static Ast::SourceLocation
loc( Ast::FileID::build_internal( "<Facing a function in 3D>" ) );
1431 /* Note that the use of a StoreValueContinuation relies on valUntyped being alive at the time the continuation is invoked.
1434 Kernel::EvalState
evalState( 0,
1437 Kernel::ContRef( new Kernel::StoreValueContinuation( & valUntyped
,
1438 Kernel::ContRef( new Kernel::ExitContinuation( & done
, loc
) ),
1441 generator_
->call( & evalState
, RefCountPtr
< const Lang::Value
>( new Lang::Transform3D( tf
) ), loc
);
1445 evalState
.expr_
->eval( & evalState
);
1448 return Helpers::down_cast
< const Lang::Drawable2D
>( valUntyped
, loc
);
1452 Lang::FacingFunction3D::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1454 throw Exceptions::MiscellaneousRequirement( "Facing functions cannot be polygonized." );
1458 Lang::FacingFunction3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1461 * At the moment, we don't search facing functions for tags!
1466 Lang::FacingFunction3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1469 * At the moment, we don't search facing functions for tags!
1475 Lang::FacingFunction3D::gcMark( Kernel::GCMarkedSet
& marked
)
1477 const_cast< Lang::Function
* >( generator_
.getPtr( ) )->gcMark( marked
);
1481 Computation::PaintedPolygon3D::PaintedPolygon3D( bool singleSided
, const Concrete::UnitFloatTriple
& normal
, Concrete::Length m
, Concrete::Length tiebreaker
)
1482 : singleSided_( singleSided
), normal_( normal
), m_( m
), tiebreaker_( tiebreaker
)
1485 Computation::PaintedPolygon3D::~PaintedPolygon3D( )
1489 Computation::PaintedPolygon3D::pushPoint( const Concrete::Coords3D
& p
)
1491 Concrete::Length tmp
= Concrete::inner( normal_
, p
) - m_
;
1492 if( tmp
.abs( ) > Computation::theTrixelizeSplicingTol
)
1494 std::ostringstream msg
;
1495 msg
<< "The 3D painted path was not flat enough (" << tmp
.offtype
< 1, 0 >( ) << " > splicingtol) to make a polygon." ;
1496 throw Exceptions::OutOfRange( strrefdup( msg
) );
1498 points_
.push_back( p
);
1502 Computation::PaintedPolygon3D::push_zBufTriangles( const Lang::Transform3D
& tf
, const Concrete::Length eyez
, std::list
< Computation::ZBufTriangle
> * triangleQueue
, bool respectSingleSided
) const
1504 // This function shall not push tiny triangles!
1506 // Note that the ZBufTriangles pushed are not completely transformed, since *this is the painter, and not transformed by tf.
1507 // The ugly solution to this is that tf must also be specified when painting the area.
1509 if( points_
.size( ) < 3 )
1514 // At the moment, convexity is assumed!
1516 typedef Computation::ZBufTriangle::ZMap ZMapType
;
1517 if( tf
.isIdentity( ) )
1519 if( respectSingleSided
&& singleSided_
)
1521 const Concrete::Coords3D
& somePoint
= points_
.front( );
1522 if( normal_
.z_
* eyez
- Concrete::inner( normal_
, somePoint
) <= 0 )
1528 RefCountPtr
< const ZMapType
> zMap( new ZMapType( normal_
, m_
, tiebreaker_
, eyez
) );
1529 typedef typeof points_ ListType
;
1530 ListType::const_iterator i
= points_
.begin( );
1531 Concrete::Coords2D p0
= i
->make2DAutomatic( eyez
);
1533 Concrete::Coords2D p1
= i
->make2DAutomatic( eyez
);
1535 for( ; i
!= points_
.end( ); ++i
)
1537 Concrete::Coords2D p2
= i
->make2DAutomatic( eyez
);
1538 // This tolerance test assures that we don't produce tiny-tiny triangles. It is an inscribed circle test.
1539 if( Computation::triangleArea( p0
, p1
, p2
) > Computation::theTrixelizeOverlapTol
* Computation::triangleSemiPerimeter( p0
, p1
, p2
) )
1541 triangleQueue
->push_back( Computation::ZBufTriangle( this,
1550 RefCountPtr
< const ZMapType
> zMap
= RefCountPtr
< const ZMapType
>( NullPtr
< const ZMapType
>( ) );
1552 Concrete::UnitFloatTriple Tnormal
= tf
.transformPlaneUnitNormal( normal_
);
1553 if( respectSingleSided
&& singleSided_
)
1555 const Concrete::Coords3D
& somePoint
= points_
.front( );
1556 if( Tnormal
.z_
* eyez
- Concrete::inner( Tnormal
, somePoint
.transformed( tf
) ) <= 0 )
1562 double ax
= fabs( normal_
.x_
);
1563 double ay
= fabs( normal_
.y_
);
1564 double az
= fabs( normal_
.z_
);
1565 Concrete::Coords3D
x0( 0, 0, 0 );
1566 if( ax
>= ay
&& ax
>= az
)
1568 x0
= Concrete::Coords3D( m_
/ normal_
.x_
, 0, 0 );
1572 x0
= Concrete::Coords3D( 0, m_
/ normal_
.y_
, 0 );
1576 x0
= Concrete::Coords3D( 0, 0, m_
/ normal_
.z_
);
1578 Concrete::Length Tm
= Concrete::inner( Tnormal
, x0
.transformed( tf
) );
1580 zMap
= RefCountPtr
< const ZMapType
>( new ZMapType( Tnormal
, Tm
, tiebreaker_
, eyez
) );
1584 typedef typeof points_ ListType
;
1585 ListType::const_iterator i
= points_
.begin( );
1586 Concrete::Coords2D p0
= i
->transformed( tf
).make2DAutomatic( eyez
);
1588 Concrete::Coords2D p1
= i
->transformed( tf
).make2DAutomatic( eyez
);
1590 for( ; i
!= points_
.end( ); ++i
)
1592 Concrete::Coords2D p2
= i
->transformed( tf
).make2DAutomatic( eyez
);
1593 // This tolerance test assures that we don't produce tiny-tiny triangles. It is an inscribed circle test.
1594 if( Computation::triangleArea( p0
, p1
, p2
) > Computation::theTrixelizeOverlapTol
* Computation::triangleSemiPerimeter( p0
, p1
, p2
) )
1596 triangleQueue
->push_back( Computation::ZBufTriangle( this,
1606 Computation::PaintedPolygon3D::computeMean( ) const
1608 Concrete::Coords3D
res( 0, 0, 0 );
1609 typedef typeof points_ ListType
;
1610 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
1614 return ( 1. / points_
.size( ) ) * res
;
1617 const Computation::FacetLatticeVertex
*
1618 Computation::FacetLatticeEdge::getOther( const FacetLatticeEdge
* e
) const
1620 if( p0_
== e
->p0_
|| p0_
== e
->p1_
)
1628 Computation::FacetLatticeEdge::sharePoint( const FacetLatticeEdge
* e
) const
1639 Computation::FacetLatticeEdge::split( const Concrete::Length eyez
,
1640 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeEdge
* > > * edgeMem
,
1641 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeVertex
* > > * vertexMem
,
1642 const Computation::FacetLatticeEdge
** child1
, const Computation::FacetLatticeEdge
** child2
) const
1651 if( eyez
== Concrete::HUGE_LENGTH
)
1653 FacetLatticeVertex
* pNew
= new FacetLatticeVertex( 0.5 * ( p0_
->p3D_
+ p1_
->p3D_
), eyez
, vertexMem
->size( ) );
1654 vertexMem
->push_back( pNew
);
1655 child1_
= new Computation::FacetLatticeEdge( p0_
, pNew
);
1656 edgeMem
->push_back( child1_
);
1657 child2_
= new Computation::FacetLatticeEdge( pNew
, p1_
);
1658 edgeMem
->push_back( child2_
);
1662 // We compute the midpoint _in_view_, and then find where this is along the 3D line.
1663 Concrete::Coords2D mid2D
= 0.5 * ( p0_
->p2D_
+ p1_
->p2D_
);
1665 // If we write the point we seek in 3D as
1666 // p0_ + lambda * ( p1_ - p0_ )
1667 // then <lambda> must solve the overdetermined system
1670 const double ra
= ( p1_
->p3D_
.z_
- p0_
->p3D_
.z_
) / eyez
;
1671 Concrete::Coords2D
a( p1_
->p3D_
.x_
- p0_
->p3D_
.x_
+ mid2D
.x_
* ra
,
1672 p1_
->p3D_
.y_
- p0_
->p3D_
.y_
+ mid2D
.y_
* ra
);
1673 const double rb
= static_cast< double >( p0_
->p3D_
.z_
/ eyez
) - 1;
1674 Concrete::Coords2D
b( p0_
->p3D_
.x_
+ mid2D
.x_
* rb
,
1675 p0_
->p3D_
.y_
+ mid2D
.y_
* rb
);
1676 const double lambda
= - Concrete::innerScalar( a
, b
) / Concrete::innerScalar( a
, a
);
1678 FacetLatticeVertex
* pNew
= new FacetLatticeVertex( ( 1 - lambda
) * p0_
->p3D_
+ lambda
* p1_
->p3D_
, eyez
, vertexMem
->size( ) );
1679 vertexMem
->push_back( pNew
);
1680 child1_
= new Computation::FacetLatticeEdge( p0_
, pNew
);
1681 edgeMem
->push_back( child1_
);
1682 child2_
= new Computation::FacetLatticeEdge( pNew
, p1_
);
1683 edgeMem
->push_back( child2_
);
1691 Computation::FacetLatticeVertex::FacetLatticeVertex( const Concrete::Coords3D
& p3D
, const Concrete::Length eyez
, const size_t i
)
1692 : p3D_( p3D
), p2D_( p3D
.make2DAutomatic( eyez
) ), i_( i
)
1695 const Computation::FacetLatticeEdge
*
1696 Computation::FacetLatticeTriangle::getOther( const Computation::FacetLatticeEdge
*ea
, const Computation::FacetLatticeEdge
*eb
) const
1706 else if( ea
== e1_
)
1714 else if( ea
== e2_
)
1723 throw Exceptions::InternalError( "FacetTriangle::getOther called with alien edge." );
1727 Computation::FacetLatticeTriangle::fitsResolution( const Concrete::Length resolution
, const Concrete::Length eyez
,
1728 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeEdge
* > > * edgeMem
,
1729 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeVertex
* > > * vertexMem
,
1730 const Computation::FacetLatticeTriangle
** child1
, const Computation::FacetLatticeTriangle
** child2
) const
1732 const Computation::FacetLatticeEdge
* ec1
;
1733 const Computation::FacetLatticeEdge
* ec2
;
1735 Concrete::Length l0
= e0_
->length2D( );
1736 Concrete::Length l1
= e1_
->length2D( );
1737 Concrete::Length l2
= e2_
->length2D( );
1738 Concrete::Length lMax
= std::max( l0
, std::max( l1
, l2
) );
1740 if( lMax
< resolution
)
1745 const Computation::FacetLatticeEdge
* ea
= e0_
;
1746 const Computation::FacetLatticeEdge
* eb
= e1_
;
1747 const Computation::FacetLatticeEdge
* ec
= e2_
;
1754 else if( l2
== lMax
)
1762 ea
->split( eyez
, edgeMem
, vertexMem
, & ec1
, & ec2
);
1763 Computation::FacetLatticeEdge
* newEdge
= new Computation::FacetLatticeEdge( ea
->midpoint( ), eb
->getOther( ea
) );
1764 edgeMem
->push_back( newEdge
);
1765 if( eb
->sharePoint( ec2
) )
1767 *child1
= new Computation::FacetLatticeTriangle( ec2
, eb
, newEdge
);
1768 *child2
= new Computation::FacetLatticeTriangle( newEdge
, ec
, ec1
);
1772 *child1
= new Computation::FacetLatticeTriangle( ec1
, eb
, newEdge
);
1773 *child2
= new Computation::FacetLatticeTriangle( newEdge
, ec
, ec2
);
1780 RefCountPtr
< const Lang::Drawable2D
>
1781 Computation::FacetLatticeTriangle::paint( const RefCountPtr
< const Computation::FacetInterpolatorGray
> & interpolator
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
, const Concrete::Length eyez
) const
1783 Kernel::GraphicsState
* metaStatePtr
= new Kernel::GraphicsState( true );
1785 metaStatePtr
->nonStrokingColor_
= interpolator
->compute( Lang::THE_3D_IDENTITY
, lights
,
1786 Computation::triangleIncenter( v0_
->p3D_
, v1_
->p3D_
, v2_
->p3D_
),
1789 RefCountPtr
< const Kernel::GraphicsState
> metaState( metaStatePtr
);
1791 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
1793 // It's a pity we have to copy duplicate those points...
1794 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v0_
->p2D_
) ) );
1795 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v1_
->p2D_
) ) );
1796 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v2_
->p2D_
) ) );
1798 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::PaintedPolygon2D( metaState
, path
) );
1801 RefCountPtr
< const Lang::Drawable2D
>
1802 Computation::FacetLatticeTriangle::paint( const RefCountPtr
< const Computation::FacetInterpolatorRGB
> & interpolator
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
, const Concrete::Length eyez
) const
1804 Kernel::GraphicsState
* metaStatePtr
= new Kernel::GraphicsState( true );
1806 metaStatePtr
->nonStrokingColor_
= interpolator
->compute( Lang::THE_3D_IDENTITY
, lights
,
1807 Computation::triangleIncenter( v0_
->p3D_
, v1_
->p3D_
, v2_
->p3D_
),
1810 RefCountPtr
< const Kernel::GraphicsState
> metaState( metaStatePtr
);
1812 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
1814 // It's a pity we have to copy duplicate those points...
1815 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v0_
->p2D_
) ) );
1816 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v1_
->p2D_
) ) );
1817 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v2_
->p2D_
) ) );
1819 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::PaintedPolygon2D( metaState
, path
) );
1823 Computation::FacetLatticeTriangle::getVertexes( const Computation::FacetLatticeVertex
** va
, const Computation::FacetLatticeVertex
** vb
, const Computation::FacetLatticeVertex
** vc
) const
1830 // This function is very close to the PDF definition of a free-form triangle mesh.
1831 // If this triangle is an extension of va--vb--vc, then va, vb, vc are updated and the corresponding flag (se PDF spec) is returned.
1832 // If this is not an extension, the value 3 is returned (which is not a legal falg value), and va, vb, vc are left unchanged.
1834 Computation::FacetLatticeTriangle::extendLattice( const Computation::FacetLatticeVertex
** va
, const Computation::FacetLatticeVertex
** vb
, const Computation::FacetLatticeVertex
** vc
) const
1836 // vc must be part of this triangle if we are to extend va--vb--vc.
1837 if( v0_
== *vc
|| v1_
== *vc
|| v2_
== *vc
)
1839 // First, we try to extend vb--vc (corresponding to flag=1)
1840 if( v0_
== *vb
|| v1_
== *vb
|| v2_
== *vb
)
1842 // We now update va and vb so that they define the edge that is extended.
1846 // Now we need to find which of our corners that is the added one.
1847 if( v0_
!= *va
&& v0_
!= *vb
)
1851 else if( v1_
!= *va
&& v1_
!= *vb
)
1862 // Then, we try to extend va--vc (corresponding to flag=2)
1863 if( v0_
== *va
|| v1_
== *va
|| v2_
== *va
)
1865 // We now update va and vb so that they define the edge that is extended.
1869 // Now we need to find which of our corners that is the added one.
1870 if( v0_
!= *va
&& v0_
!= *vb
)
1874 else if( v1_
!= *va
&& v1_
!= *vb
)
1890 Computation::FacetLatticeTriangle::display2D( std::ostream
& os
) const
1892 Concrete::Length lMax
= Concrete::ZERO_LENGTH
;
1894 Concrete::Length tmp
= v0_
->p2D_
.distanceTo( v1_
->p2D_
);
1901 Concrete::Length tmp
= v1_
->p2D_
.distanceTo( v2_
->p2D_
);
1908 Concrete::Length tmp
= v2_
->p2D_
.distanceTo( v0_
->p2D_
);
1915 os
<< "Triangle ( " << v0_
->p2D_
<< " -- " << v1_
->p2D_
<< " -- " << v2_
->p2D_
<< " ) "
1916 << " with 2D area " << Concrete::Area::offtype( Computation::triangleArea( v0_
->p2D_
, v1_
->p2D_
, v2_
->p2D_
) )
1917 << " and longest side " << Lang::Length( lMax
) ;
1921 Computation::FacetLatticeTriangle::display3D( std::ostream
& os
) const
1923 os
<< "Triangle ( " << v0_
->p3D_
<< " -- " << v1_
->p3D_
<< " -- " << v2_
->p3D_
<< " )" ;
1928 Computation::PaintedPolygon3D::makeLattice( PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeTriangle
* > > * lattice
,
1929 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeEdge
* > > * edgeMem
,
1930 PtrOwner_back_Access
< std::list
< const FacetLatticeVertex
* > > * vertexMem
,
1931 const Concrete::Length viewResolution
,
1932 const Concrete::Length eyez
, const Lang::Transform3D
& tf
) const
1934 if( points_
.size( ) < 3 )
1936 throw Exceptions::InternalError( "Less than three points in PaintedPolygon3D::makeLattice!" );
1939 std::list
< const Computation::FacetLatticeTriangle
* > jobQueue
;
1941 typedef typeof points_ ListType
;
1943 if( points_
.size( ) == 3 )
1945 ListType::const_iterator i
= points_
.begin( );
1946 Computation::FacetLatticeVertex
* p0
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1947 vertexMem
->push_back( p0
);
1949 Computation::FacetLatticeVertex
* p1
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1950 vertexMem
->push_back( p1
);
1952 Computation::FacetLatticeVertex
* p2
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1953 vertexMem
->push_back( p2
);
1955 Computation::FacetLatticeEdge
* e0
= new Computation::FacetLatticeEdge( p0
, p1
);
1956 edgeMem
->push_back( e0
);
1957 Computation::FacetLatticeEdge
* e1
= new Computation::FacetLatticeEdge( p1
, p2
);
1958 edgeMem
->push_back( e1
);
1959 Computation::FacetLatticeEdge
* e2
= new Computation::FacetLatticeEdge( p2
, p0
);
1960 edgeMem
->push_back( e2
);
1962 jobQueue
.push_back( new Computation::FacetLatticeTriangle( e0
, e1
, e2
) );
1966 ListType::const_iterator i
= points_
.begin( );
1967 Computation::FacetLatticeVertex
* p0
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1968 vertexMem
->push_back( p0
);
1970 Computation::FacetLatticeVertex
* p1
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1971 vertexMem
->push_back( p1
);
1974 Computation::FacetLatticeEdge
* e0
= new Computation::FacetLatticeEdge( p0
, p1
);
1975 edgeMem
->push_back( e0
);
1977 for( ; i
!= points_
.end( ); ++i
)
1979 Computation::FacetLatticeVertex
* p2
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1980 vertexMem
->push_back( p2
);
1982 Computation::FacetLatticeEdge
* e1
= new Computation::FacetLatticeEdge( p1
, p2
);
1983 edgeMem
->push_back( e1
);
1985 Computation::FacetLatticeEdge
* e2
= new Computation::FacetLatticeEdge( p2
, p0
);
1986 edgeMem
->push_back( e2
);
1988 jobQueue
.push_back( new Computation::FacetLatticeTriangle( e0
, e1
, e2
) );
1995 while( ! jobQueue
.empty( ) )
1997 const Computation::FacetLatticeTriangle
* currentTriangle
= jobQueue
.front( );
1998 jobQueue
.pop_front( );
1999 const Computation::FacetLatticeTriangle
* child1
= 0;
2000 const Computation::FacetLatticeTriangle
* child2
= 0;
2001 if( currentTriangle
->fitsResolution( viewResolution
, eyez
, edgeMem
, vertexMem
, & child1
, & child2
) )
2003 lattice
->push_back( currentTriangle
);
2007 jobQueue
.push_back( child1
);
2008 jobQueue
.push_back( child2
);
2009 delete currentTriangle
;
2014 Computation::StrokedLine3D::StrokedLine3D( const Concrete::Coords3D
& p0
, const Concrete::Coords3D
& p1
, const RefCountPtr
< const Kernel::GraphicsState
> metaState
)
2015 : p0_( p0
), p1_( p1
), metaState_( metaState
)
2018 Computation::StrokedLine3D::~StrokedLine3D( )
2022 Computation::StrokedLine3D::push_zBufLine( const Lang::Transform3D
& tf
, const Concrete::Length eyez
, std::list
< const Computation::ZBufLine
* > * lineQueue
) const
2024 typedef Computation::ZBufLine::ZMap ZMapType
;
2025 typedef const Bezier::PolyCoeffs
< Concrete::Coords2D
> ViewType
;
2026 RefCountPtr
< ViewType
> nullView
= RefCountPtr
< ViewType
>( NullPtr
< ViewType
>( ) );
2027 if( tf
.isIdentity( ) )
2029 Concrete::Coords3D d
= p1_
- p0_
;
2030 RefCountPtr
< const ZMapType
> zMap( new ZMapType( p0_
, d
.directionNoFail( ), eyez
) );
2031 lineQueue
->push_back( new Computation::ZBufLine( this, zMap
, nullView
, p0_
.make2DAutomatic( eyez
), p1_
.make2DAutomatic( eyez
) ) );
2035 Concrete::Coords3D tfp0
= p0_
.transformed( tf
);
2036 Concrete::Coords3D tfp1
= p1_
.transformed( tf
);
2037 Concrete::Coords3D d
= tfp1
- tfp0
;
2038 RefCountPtr
< const ZMapType
> zMap( new ZMapType( tfp0
, d
.directionNoFail( ), eyez
) );
2039 lineQueue
->push_back( new Computation::ZBufLine( this, zMap
, nullView
, tfp0
.make2DAutomatic( eyez
), tfp1
.make2DAutomatic( eyez
) ) );
2044 Computation::StrokedSplineSegment3D::StrokedSplineSegment3D( const Concrete::Coords3D
& p0
, const Concrete::Coords3D
& p0front
, const Concrete::Coords3D
& p1rear
, const Concrete::Coords3D
& p1
, const RefCountPtr
< const Kernel::GraphicsState
> metaState
)
2045 : Computation::StrokedLine3D( p0
, p1
, metaState
),
2046 p0front_( p0front
),
2050 Computation::StrokedSplineSegment3D::~StrokedSplineSegment3D( )
2054 Computation::StrokedSplineSegment3D::push_zBufLine( const Lang::Transform3D
& tf
, const Concrete::Length eyez
, std::list
< const Computation::ZBufLine
* > * lineQueue
) const
2056 typedef Computation::ZBufLine::ZMap ZMapType
;
2057 typedef const Bezier::PolyCoeffs
< Concrete::Coords2D
> ViewType
;
2058 if( tf
.isIdentity( ) )
2060 Concrete::Coords3D d
= p1_
- p0_
;
2061 RefCountPtr
< const ZMapType
> zMap( new ZMapType( p0_
, d
.directionNoFail( ), eyez
) );
2062 RefCountPtr
< ViewType
> bezierView
= RefCountPtr
< ViewType
>( new ViewType( Bezier::ControlPoints
< Concrete::Coords2D
>( p0_
.make2DAutomatic( eyez
), p0front_
.make2DAutomatic( eyez
), p1rear_
.make2DAutomatic( eyez
), p1_
.make2DAutomatic( eyez
) ) ) );
2063 lineQueue
->push_back( new Computation::ZBufLine( this, zMap
, bezierView
, p0_
.make2DAutomatic( eyez
), p1_
.make2DAutomatic( eyez
) ) );
2067 Concrete::Coords3D tfp0
= p0_
.transformed( tf
);
2068 Concrete::Coords3D tfp0front
= p0front_
.transformed( tf
);
2069 Concrete::Coords3D tfp1rear
= p1rear_
.transformed( tf
);
2070 Concrete::Coords3D tfp1
= p1_
.transformed( tf
);
2071 Concrete::Coords3D d
= tfp1
- tfp0
;
2072 RefCountPtr
< const ZMapType
> zMap( new ZMapType( tfp0
, d
.directionNoFail( ), eyez
) );
2073 RefCountPtr
< ViewType
> bezierView
= RefCountPtr
< ViewType
>( new ViewType( Bezier::ControlPoints
< Concrete::Coords2D
>( tfp0
.make2DAutomatic( eyez
), tfp0front
.make2DAutomatic( eyez
), tfp1rear
.make2DAutomatic( eyez
), tfp1
.make2DAutomatic( eyez
) ) ) );
2074 lineQueue
->push_back( new Computation::ZBufLine( this, zMap
, bezierView
, tfp0
.make2DAutomatic( eyez
), tfp1
.make2DAutomatic( eyez
) ) );
2079 Computation::FilledPolygon3D::FilledPolygon3D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
,
2080 const Concrete::UnitFloatTriple
& normal
, Concrete::Length m
,
2081 Concrete::Length tiebreaker
)
2082 : Computation::PaintedPolygon3D( false, normal
, m
, tiebreaker
), metaState_( metaState
) // false means not single-sided.
2085 Computation::FilledPolygon3D::~FilledPolygon3D( )
2088 RefCountPtr
< const Lang::PaintedPolygon2D
>
2089 Computation::FilledPolygon3D::polygon_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
) const
2091 // A FilledPolygon3D is characterized by that it doesn't take notice about the lights or orientation.
2093 Concrete::Length eyez
= dyn
->getEyeZ( );
2095 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
2097 if( tf
.isIdentity( ) )
2099 typedef typeof points_ ListType
;
2100 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
2102 path
->push_back( new Concrete::PathPoint2D( i
->make2D( eyez
) ) );
2107 typedef typeof points_ ListType
;
2108 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
2110 path
->push_back( new Concrete::PathPoint2D( i
->transformed( tf
).make2D( eyez
) ) );
2114 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::PaintedPolygon2D( metaState_
, path
) );
2117 RefCountPtr
< const Lang::Color
>
2118 Computation::FilledPolygon3D::getColor( ) const
2120 return metaState_
->nonStrokingColor_
;
2124 Computation::FilledPolygon3D::gcMark( Kernel::GCMarkedSet
& marked
)
2126 // const_cast< Kernel::GraphicsState * >( metaState_.getPtr( ) )->gcMark( marked );
2129 Computation::NullPolygon3D::NullPolygon3D( )
2130 : Computation::PaintedPolygon3D( true, Concrete::UnitFloatTriple( 1., 0., 0., 1. ), 0, Concrete::ZERO_LENGTH
)
2133 Computation::NullPolygon3D::~NullPolygon3D( )
2136 RefCountPtr
< const Lang::PaintedPolygon2D
>
2137 Computation::NullPolygon3D::polygon_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
) const
2139 throw Exceptions::InternalError( "NullPolygon3D::polygon_to2D was invoked!" );
2140 // return Lang::THE_NULL_POLYGON2D;
2143 RefCountPtr
< const Lang::Color
>
2144 Computation::NullPolygon3D::getColor( ) const
2146 return Lang::THE_BLACK
;
2150 Computation::NullPolygon3D::gcMark( Kernel::GCMarkedSet
& marked
)
2154 Lang::PaintedPolygon2D::PaintedPolygon2D( RefCountPtr
< const Kernel::GraphicsState
> metaState
, RefCountPtr
< const Lang::ElementaryPath2D
> path
)
2155 : Lang::PaintedPath2D( metaState
, "E" ) // "E" for "extended fill"
2157 if( ! path
->isClosed( ) )
2159 throw Exceptions::InternalError( "Attempt to create PaintedPolygon2D with non-closed path." );
2164 Lang::PaintedPolygon2D::~PaintedPolygon2D( )
2167 RefCountPtr
< const Lang::Drawable2D
>
2168 Lang::PaintedPolygon2D::clip( std::list
< Computation::ZBufTriangle
> * regions
, const RefCountPtr
< const Lang::PaintedPolygon2D
> selfRef
) const
2170 if( regions
->empty( ) )
2172 throw Exceptions::InternalError( "Empty list of regions in PaintedPolygon2D::clip. (This triangle should not have been generated at all!)" );
2174 if( regions
->size( ) == 1 )
2176 const Computation::ZBufTriangle
& theClip
= regions
->front( );
2177 const Lang::ElementaryPath2D
& paintPath
= * path_
.front( );
2178 bool isInside
= true;
2179 for( Lang::ElementaryPath2D::const_iterator i
= paintPath
.begin( ); i
!= paintPath
.end( ); ++i
)
2181 if( ! theClip
.contains( *((*i
)->mid_
), Computation::theTrixelizeOverlapTol
) )
2193 // If we reach here, clipping shall be done
2194 Lang::Clipped2D
* resPtr
= new Lang::Clipped2D( selfRef
, "W" );
2195 Lang::ZBuf::trianglesToPolys( regions
, resPtr
);
2196 RefCountPtr
< const Lang::Clipped2D
> res( resPtr
);
2198 if( selfRef
->isContainedIn( resPtr
) )
2203 const bool SHOW_POLYS
= false;
2206 return res
->debugPolys( );
2214 Lang::PaintedPath2D::isContainedIn( const Lang::Clipped2D
* clipping
) const
2216 if( ! clipping
->isSingleConvexPoly( Computation::theTrixelizeOverlapTol
) )
2221 typedef typeof path_ PathType
;
2222 for( PathType::const_iterator subpath
= path_
.begin( ); subpath
!= path_
.end( ); ++subpath
)
2224 typedef typeof **subpath SubpathType
;
2225 for( SubpathType::const_iterator i
= (*subpath
)->begin( ); i
!= (*subpath
)->end( ); ++i
)
2227 Concrete::PathPoint2D
* pathPoint
= *i
;
2228 if( pathPoint
->rear_
!= pathPoint
->mid_
||
2229 pathPoint
->front_
!= pathPoint
->mid_
)
2233 if( ! clipping
->convexPolyContains( *(pathPoint
->mid_
), Computation::theTrixelizeOverlapTol
) )
2244 Lang::PaintedPath3D::PaintedPath3D( RefCountPtr
< const Kernel::GraphicsState
> metaState
,
2245 const char * paintCmd
, Concrete::Length tiebreaker
)
2246 : metaState_( metaState
), paintCmd_( paintCmd
), tiebreaker_( tiebreaker
)
2249 Lang::PaintedPath3D::PaintedPath3D( RefCountPtr
< const Kernel::GraphicsState
> metaState
,
2250 RefCountPtr
< const Lang::ElementaryPath3D
> path
,
2251 const char * paintCmd
, Concrete::Length tiebreaker
)
2252 : metaState_( metaState
), paintCmd_( paintCmd
), tiebreaker_( tiebreaker
)
2257 Lang::PaintedPath3D::PaintedPath3D( RefCountPtr
< const Kernel::GraphicsState
> metaState
,
2258 RefCountPtr
< const Lang::MultiPath3D
> paths
,
2259 const char * paintCmd
, Concrete::Length tiebreaker
)
2260 : metaState_( metaState
), paintCmd_( paintCmd
), tiebreaker_( tiebreaker
)
2262 for( Lang::MultiPath3D::const_iterator i
= paths
->begin( ); i
!= paths
->end( ); ++i
)
2265 typedef const Lang::ElementaryPath3D ArgType
;
2266 RefCountPtr
< ArgType
> subpath
= (*i
).down_cast
< ArgType
>( );
2267 if( subpath
!= NullPtr
< ArgType
>( ) )
2269 addSubPath( subpath
);
2275 typedef const Lang::CompositePath3D ArgType
;
2276 ArgType
* subpath
= dynamic_cast< ArgType
* >( (*i
).getPtr( ) );
2279 addSubPath( subpath
->getElementaryPath( ) );
2283 throw Exceptions::InternalError( "Painting 3D path: Encountered a subpath of unexpected type" );
2287 Lang::PaintedPath3D::~PaintedPath3D( )
2290 RefCountPtr
< const Lang::Class
> Lang::PaintedPath3D::TypeID( new Lang::SystemFinalClass( strrefdup( "PaintedPath3D" ) ) );
2291 TYPEINFOIMPL( PaintedPath3D
);
2294 Lang::PaintedPath3D::addSubPath( RefCountPtr
< const Lang::ElementaryPath3D
> subpath
)
2296 path_
.push_back( subpath
);
2299 RefCountPtr
< const Lang::Drawable2D
>
2300 Lang::PaintedPath3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2302 Concrete::Length eyez
= dyn
->getEyeZ( );
2304 RefCountPtr
< const Lang::Group2D
> res( Lang::THE_NULL2D
);
2306 if( tf
.isIdentity( ) )
2308 if( ! metaState_
->dash_
->isSolid( ) && *paintCmd_
== 'S' )
2310 for( std::list
< RefCountPtr
< const Lang::ElementaryPath3D
> >::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
2312 (*i
)->dashifyIn2D( & res
, eyez
, metaState_
);
2317 for( std::list
< RefCountPtr
< const Lang::ElementaryPath3D
> >::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
2319 res
= RefCountPtr
< const Lang::Group2D
>( new Lang::GroupPair2D( RefCountPtr
< const Lang::Drawable2D
>( new Lang::PaintedPath2D( metaState_
, (*i
)->make2D( eyez
), paintCmd_
) ),
2327 if( ! metaState_
->dash_
->isSolid( ) && *paintCmd_
== 'S' )
2329 for( std::list
< RefCountPtr
< const Lang::ElementaryPath3D
> >::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
2331 (*i
)->elementaryTransformed( tf
)->dashifyIn2D( & res
, eyez
, metaState_
);
2336 for( std::list
< RefCountPtr
< const Lang::ElementaryPath3D
> >::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
2338 res
= RefCountPtr
< const Lang::Group2D
>( new Lang::GroupPair2D( RefCountPtr
< const Lang::Drawable2D
>( new Lang::PaintedPath2D( metaState_
,
2339 (*i
)->elementaryTransformed( tf
)->make2D( eyez
),
2350 Lang::PaintedPath3D::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2352 if( strcmp( paintCmd_
, "S" ) == 0 )
2354 typedef typeof path_ ListType
;
2355 for( ListType::const_iterator subi
= path_
.begin( ); subi
!= path_
.end( ); ++subi
)
2357 const RefCountPtr
< const Lang::ElementaryPath3D
> & theSub
= *subi
;
2359 if( theSub
->size( ) < 2 )
2364 typedef typeof *theSub SubListType
;
2365 SubListType::const_iterator i
= theSub
->begin( );
2366 Concrete::Coords3D p0
= (*i
)->mid_
->transformed( tf
);
2367 SubListType::const_iterator iLast
= i
;
2369 for( ; i
!= theSub
->end( ); iLast
= i
, ++i
)
2371 Concrete::Coords3D p1
= (*i
)->mid_
->transformed( tf
);
2372 if( (*iLast
)->front_
!= (*iLast
)->mid_
|| (*i
)->rear_
!= (*i
)->mid_
)
2374 linePile
->push_back( RefCountPtr
< Computation::StrokedSplineSegment3D
>
2375 ( new Computation::StrokedSplineSegment3D( p0
, (*iLast
)->front_
->transformed( tf
), (*i
)->rear_
->transformed( tf
), p1
, metaState_
) ) );
2379 linePile
->push_back( RefCountPtr
< Computation::StrokedLine3D
>
2380 ( new Computation::StrokedLine3D( p0
, p1
, metaState_
) ) );
2384 if( theSub
->isClosed( ) )
2386 i
= theSub
->begin( );
2387 Concrete::Coords3D p1
= (*i
)->mid_
->transformed( tf
);
2388 if( (*iLast
)->front_
!= (*iLast
)->mid_
|| (*i
)->rear_
!= (*i
)->mid_
)
2390 linePile
->push_back( RefCountPtr
< Computation::StrokedSplineSegment3D
>
2391 ( new Computation::StrokedSplineSegment3D( p0
, (*iLast
)->front_
->transformed( tf
), (*i
)->rear_
->transformed( tf
), p1
, metaState_
) ) );
2395 linePile
->push_back( RefCountPtr
< Computation::StrokedLine3D
>
2396 ( new Computation::StrokedLine3D( p0
, p1
, metaState_
) ) );
2404 if( ! ( strcmp( paintCmd_
, "f" ) == 0 ||
2405 strcmp( paintCmd_
, "B" ) == 0 ) )
2407 throw Exceptions::MiscellaneousRequirement( "Only stroked and (non-*) filled polygons can be put i a z buffer." );
2411 // When we get here we know that the paintCmd_ is "f" or "B", that is, a plain fill.
2413 // if( path.size( ) > 1 )
2415 // WARN_OR_THROW( Exceptionssha::MiscellanueousRequirement( "The result from triangularizing a composite path may not be what is expected." ) );
2418 typedef typeof path_ ListType
;
2419 for( ListType::const_iterator subi
= path_
.begin( ); subi
!= path_
.end( ); ++subi
)
2421 const RefCountPtr
< const Lang::ElementaryPath3D
> & theSub
= *subi
;
2423 if( theSub
->size( ) < 3 )
2427 if( ! theSub
->isClosed( ) )
2432 typedef typeof *theSub SubListType
;
2434 RefCountPtr
< Computation::FilledPolygon3D
> newPoly
= RefCountPtr
< Computation::FilledPolygon3D
>( NullPtr
< Computation::FilledPolygon3D
>( ) );
2436 // First we must compute an equation for the polygon!
2438 Concrete::Coords3D
p0( 0, 0, 0 );
2439 Concrete::Coords3D
p1( 0, 0, 0 );
2440 Concrete::Coords3D
p2( 0, 0, 0 );
2441 theSub
->getRepresentativePoints( tf
, & p0
, & p1
, & p2
);
2445 Concrete::UnitFloatTriple normal
= Concrete::crossDirection( p2
- p0
, p1
- p0
);
2446 Concrete::Length m
= Concrete::inner( normal
, p0
);
2447 newPoly
= RefCountPtr
< Computation::FilledPolygon3D
>( new Computation::FilledPolygon3D( metaState_
, normal
, m
, tiebreaker_
) );
2449 catch( const NonLocalExit::CrossDirectionOfParallel
& ball
)
2451 // This means that the crossDirection called failed because the vectors were parallel.
2452 // A polygon of lower dimension is invisible, so we may just continue
2457 zBufPile
->push_back( newPoly
);
2459 for( SubListType::const_iterator i
= theSub
->begin( ); i
!= theSub
->end( ); ++i
)
2461 if( (*i
)->front_
!= (*i
)->mid_
|| (*i
)->rear_
!= (*i
)->mid_
)
2463 throw "Corner has handle";
2465 newPoly
->pushPoint( (*i
)->mid_
->transformed( tf
) );
2471 Lang::PaintedPath3D::gcMark( Kernel::GCMarkedSet
& marked
)
2475 Lang::SingleSided3DGray::SingleSided3DGray( const RefCountPtr
< const Lang::ElementaryPath3D
> & points
,
2476 const RefCountPtr
< const Computation::FacetInterpolatorGray
> & interpolator
,
2478 const Concrete::UnitFloatTriple
& polygonUnitNormal
,
2480 Concrete::Length tiebreaker
,
2481 Concrete::Length viewResolution
,
2482 Computation::FacetShadeOrder shadeOrder
)
2483 : points_( points
), interpolator_( interpolator
), singleSided_( singleSided
), polygonUnitNormal_( polygonUnitNormal
), m_( m
), tiebreaker_( tiebreaker
),
2484 viewResolution_( viewResolution
), shadeOrder_( shadeOrder
)
2487 Lang::SingleSided3DGray::~SingleSided3DGray( )
2490 RefCountPtr
< const Lang::Class
> Lang::SingleSided3DGray::TypeID( new Lang::SystemFinalClass( strrefdup( "SingleSided3D(gray)" ) ) );
2491 TYPEINFOIMPL( SingleSided3DGray
);
2493 RefCountPtr
< const Lang::Drawable2D
>
2494 Lang::SingleSided3DGray::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2496 throw Exceptions::NotImplemented( "SingleSided3DGray::typed_to2D; What light scene should be used?" );
2500 Lang::SingleSided3DGray::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2502 Concrete::UnitFloatTriple Tnormal
= tf
.transformPlaneUnitNormal( polygonUnitNormal_
);
2504 double ax
= fabs( polygonUnitNormal_
.x_
);
2505 double ay
= fabs( polygonUnitNormal_
.y_
);
2506 double az
= fabs( polygonUnitNormal_
.z_
);
2507 Concrete::Coords3D
x0( 0, 0, 0 );
2508 if( ax
>= ay
&& ax
>= az
)
2510 x0
= Concrete::Coords3D( m_
/ polygonUnitNormal_
.x_
, 0, 0 );
2514 x0
= Concrete::Coords3D( 0, m_
/ polygonUnitNormal_
.y_
, 0 );
2518 x0
= Concrete::Coords3D( 0, 0, m_
/ polygonUnitNormal_
.z_
);
2520 Concrete::Length Tm
= Concrete::inner( Tnormal
, x0
.transformed( tf
) );
2522 RefCountPtr
< Computation::SingleSidedPolygon3DGray
> res
=
2523 RefCountPtr
< Computation::SingleSidedPolygon3DGray
>
2524 ( new Computation::SingleSidedPolygon3DGray( interpolator_
->transformed( tf
),
2532 typedef Lang::ElementaryPath3D ListType
;
2533 for( ListType::const_iterator i
= points_
->begin( ); i
!= points_
->end( ); ++i
)
2535 // The creator of *this is responsible for asserting that there are no handles at the pathpoints.
2536 res
->pushPoint( (*i
)->mid_
->transformed( tf
) );
2540 zBufPile
->push_back( res
);
2544 Lang::SingleSided3DGray::gcMark( Kernel::GCMarkedSet
& marked
)
2546 const_cast< Lang::ElementaryPath3D
* >( points_
.getPtr( ) )->gcMark( marked
);
2547 const_cast< Computation::FacetInterpolatorGray
* >( interpolator_
.getPtr( ) )->gcMark( marked
);
2551 Lang::SingleSided3DRGB::SingleSided3DRGB( const RefCountPtr
< const Lang::ElementaryPath3D
> & points
,
2552 const RefCountPtr
< const Computation::FacetInterpolatorRGB
> & interpolator
,
2554 const Concrete::UnitFloatTriple
& polygonUnitNormal
,
2556 Concrete::Length tiebreaker
,
2557 Concrete::Length viewResolution
,
2558 Computation::FacetShadeOrder shadeOrder
)
2559 : points_( points
), interpolator_( interpolator
), singleSided_( singleSided
), polygonUnitNormal_( polygonUnitNormal
), m_( m
), tiebreaker_( tiebreaker
),
2560 viewResolution_( viewResolution
), shadeOrder_( shadeOrder
)
2563 Lang::SingleSided3DRGB::~SingleSided3DRGB( )
2566 RefCountPtr
< const Lang::Class
> Lang::SingleSided3DRGB::TypeID( new Lang::SystemFinalClass( strrefdup( "SingleSided3D(RGB)" ) ) );
2567 TYPEINFOIMPL( SingleSided3DRGB
);
2569 RefCountPtr
< const Lang::Drawable2D
>
2570 Lang::SingleSided3DRGB::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2572 throw Exceptions::NotImplemented( "SingleSided3DRGB::typed_to2D; What light scene should be used?" );
2576 Lang::SingleSided3DRGB::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2578 Concrete::UnitFloatTriple Tnormal
= tf
.transformPlaneUnitNormal( polygonUnitNormal_
);
2580 double ax
= fabs( polygonUnitNormal_
.x_
);
2581 double ay
= fabs( polygonUnitNormal_
.y_
);
2582 double az
= fabs( polygonUnitNormal_
.z_
);
2583 Concrete::Coords3D
x0( 0, 0, 0 );
2584 if( ax
>= ay
&& ax
>= az
)
2586 x0
= Concrete::Coords3D( m_
/ polygonUnitNormal_
.x_
, 0, 0 );
2590 x0
= Concrete::Coords3D( 0, m_
/ polygonUnitNormal_
.y_
, 0 );
2594 x0
= Concrete::Coords3D( 0, 0, m_
/ polygonUnitNormal_
.z_
);
2596 Concrete::Length Tm
= Concrete::inner( Tnormal
, x0
.transformed( tf
) );
2598 RefCountPtr
< Computation::SingleSidedPolygon3DRGB
> res
=
2599 RefCountPtr
< Computation::SingleSidedPolygon3DRGB
>
2600 ( new Computation::SingleSidedPolygon3DRGB( interpolator_
->transformed( tf
),
2608 typedef Lang::ElementaryPath3D ListType
;
2609 for( ListType::const_iterator i
= points_
->begin( ); i
!= points_
->end( ); ++i
)
2611 // The creator of *this is responsible for asserting that there are no handles at the pathpoints.
2612 res
->pushPoint( (*i
)->mid_
->transformed( tf
) );
2616 zBufPile
->push_back( res
);
2620 Lang::SingleSided3DRGB::gcMark( Kernel::GCMarkedSet
& marked
)
2622 const_cast< Lang::ElementaryPath3D
* >( points_
.getPtr( ) )->gcMark( marked
);
2623 const_cast< Computation::FacetInterpolatorRGB
* >( interpolator_
.getPtr( ) )->gcMark( marked
);
2628 Lang::ZBuf::ZBuf( const RefCountPtr
< std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > > & pile
, const RefCountPtr
< std::list
< RefCountPtr
< Computation::StrokedLine3D
> > > & linePile
, const RefCountPtr
< std::list
< RefCountPtr
< const Lang::LightSource
> > > & lightPile
, const RefCountPtr
< const Kernel::GraphicsState
> & metaState
)
2629 : metaState_( metaState
), pile_( pile
), linePile_( linePile
), lightPile_( lightPile
)
2632 Lang::ZBuf::~ZBuf( )
2636 Lang::ZBuf::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2639 typedef typeof *pile_ ListType
;
2640 for( ListType::const_iterator i
= pile_
->begin( ); i
!= pile_
->end( ); ++i
)
2642 zBufPile
->push_back( *i
);
2646 typedef typeof *linePile_ ListType
;
2647 for( ListType::const_iterator i
= linePile_
->begin( ); i
!= linePile_
->end( ); ++i
)
2649 linePile
->push_back( *i
);
2655 Lang::ZBuf::gcMark( Kernel::GCMarkedSet
& marked
)
2657 // At the time of writing, PaintedPolygon3D is not involved in gc.
2661 Lang::ZSorter::ZSorter( const RefCountPtr
< std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > > & pile
, const RefCountPtr
< std::list
< RefCountPtr
< Computation::StrokedLine3D
> > > & linePile
, const RefCountPtr
< std::list
< RefCountPtr
< const Lang::LightSource
> > > & lightPile
, const RefCountPtr
< const Kernel::GraphicsState
> & metaState
)
2662 : metaState_( metaState
), pile_( pile
), linePile_( linePile
), lightPile_( lightPile
)
2665 Lang::ZSorter::~ZSorter( )
2669 Lang::ZSorter::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2672 typedef typeof *pile_ ListType
;
2673 for( ListType::const_iterator i
= pile_
->begin( ); i
!= pile_
->end( ); ++i
)
2675 zBufPile
->push_back( *i
);
2679 typedef typeof *linePile_ ListType
;
2680 for( ListType::const_iterator i
= linePile_
->begin( ); i
!= linePile_
->end( ); ++i
)
2682 linePile
->push_back( *i
);
2688 Lang::ZSorter::gcMark( Kernel::GCMarkedSet
& marked
)
2690 // At the time of writing, PaintedPolygon3D is not involved in gc.
2694 Lang::Transformed3D::Transformed3D( RefCountPtr
< const Lang::Drawable3D
> element
, const Lang::Transform3D
& mytf
)
2695 : mytf_( mytf
), element_( element
)
2698 Lang::Transformed3D::~Transformed3D( )
2701 RefCountPtr
< const Lang::Drawable2D
>
2702 Lang::Transformed3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2704 return element_
->typed_to2D( dyn
, Lang::Transform3D( tf
, mytf_
), element_
);
2708 Lang::Transformed3D::polygonize( std::list
< RefCountPtr
< Computation::PaintedPolygon3D
> > * zBufPile
, std::list
< RefCountPtr
< Computation::StrokedLine3D
> > * linePile
, const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2710 element_
->polygonize( zBufPile
, linePile
, dyn
, Lang::Transform3D( tf
, mytf_
), element_
);
2714 Lang::Transformed3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
2716 element_
->findTags( dst
, dyn
, key
, Lang::Transform3D( tf
, mytf_
) );
2720 Lang::Transformed3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
2723 element_
->findOneTag( evalState
, key
, Lang::Transform3D( tf
, mytf_
) );
2727 Lang::Transformed3D::gcMark( Kernel::GCMarkedSet
& marked
)
2729 const_cast< Lang::Drawable3D
* >( element_
.getPtr( ) )->gcMark( marked
);
2732 Lang::Text::Text( const RefCountPtr
< const Kernel::TextState
> & textState
, const RefCountPtr
< const std::list
< RefCountPtr
< const Lang::TextOperation
> > > & elements
, const RefCountPtr
< const Lang::ElementaryPath2D
> & mybbox
)
2733 : textState_( textState
), elements_( elements
), mybbox_( mybbox
)
2736 Lang::Text::~Text( )
2740 Lang::Text::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
2742 if( textState_
->font_
->outline( ) )
2744 if( ( pdfState
->text_
.knockout_
& Kernel::TextState::KNOCKOUT_UNDEFINED_BIT
) != 0 &&
2745 ( pdfState
->text_
.knockout_
& Kernel::TextState::KNOCKOUT_FLAG_BIT
) == 0 )
2747 Kernel::TextState newState
;
2748 newState
.knockout_
= 0; /* Clear the KNOCKOUT_FLAG_BIT. */
2749 Helpers::newTransparencyGroup( RefCountPtr
< const Lang::Drawable2D
>
2750 ( new Lang::Text( RefCountPtr
< const Kernel::TextState
>( new Kernel::TextState( newState
, *textState_
) ),
2753 false, /* The group shall be isolated. */
2754 false, /* Not knockout. */
2755 Lang::THE_INHERITED_COLOR_SPACE
)->shipout( os
, pdfState
, tf
);
2759 Lang::Transform2D
textMatrix( 0, 0, 0, 0, Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
);
2760 Lang::Transform2D
lineMatrix( 0, 0, 0, 0, Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
);
2761 lineMatrix
.replaceBy( Lang::THE_2D_IDENTITY
);
2762 textMatrix
.replaceBy( lineMatrix
);
2763 typedef typeof *elements_ ListType
;
2764 for( ListType::const_iterator i
= elements_
->begin( ); i
!= elements_
->end( ); ++i
)
2766 (*i
)->shipout_outlined( os
, pdfState
, tf
, & textMatrix
, & lineMatrix
, 0 ); /* 0 means that this is a painting operation, not clipping. */
2772 pdfState
->resources_
->requireProcedureSet( SimplePDF::PDF_Resources::PROC_SET_TEXT
);
2774 os
<< "BT" << std::endl
;
2775 if( ! tf
.isIdentity( ) )
2778 os
<< " Tm" << std::endl
;
2781 pdfState
->text_
.synchKnockout( os
, textState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
2783 typedef typeof *elements_ ListType
;
2784 for( ListType::const_iterator i
= elements_
->begin( ); i
!= elements_
->end( ); ++i
)
2786 (*i
)->shipout( os
, pdfState
, tf
);
2788 os
<< "ET" << std::endl
;
2793 Lang::Text::shipout_clip( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
, const RefCountPtr
< const Lang::Drawable2D
> & content
) const
2795 if( textState_
->font_
->outline( ) )
2797 Lang::Transform2D
textMatrix( 0, 0, 0, 0, Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
);
2798 Lang::Transform2D
lineMatrix( 0, 0, 0, 0, Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
);
2799 textMatrix
.replaceBy( Lang::THE_2D_IDENTITY
);
2800 lineMatrix
.replaceBy( Lang::THE_2D_IDENTITY
);
2801 if( ( pdfState
->text_
.knockout_
& Kernel::TextState::KNOCKOUT_UNDEFINED_BIT
) != 0 &&
2802 ( pdfState
->text_
.knockout_
& Kernel::TextState::KNOCKOUT_FLAG_BIT
) == 0 )
2804 /* If the text knockout mode is false (by default, it is true), we emulate the effect by creating a temporary
2805 * object with default knockout mode inside a transparency group with the correct knockout mode, and then
2806 * shipout that object instead.
2808 Kernel::TextState newState
;
2809 newState
.knockout_
= 0; /* Clear the KNOCKOUT_FLAG_BIT. */
2810 Helpers::newTransparencyGroup( RefCountPtr
< const Lang::Drawable2D
>
2811 ( new Lang::TextMasked2D( content
,
2812 RefCountPtr
< const Lang::Text
>
2813 ( new Lang::Text( RefCountPtr
< const Kernel::TextState
>( new Kernel::TextState( newState
, *textState_
) ),
2816 false, /* The group shall be isolated. */
2817 false, /* Not knockout. */
2818 Lang::THE_INHERITED_COLOR_SPACE
)->shipout( os
, pdfState
, tf
);
2822 RefCountPtr
< const Lang::ElementaryPath2D
> theBBox
= content
->bbox( Lang::Drawable2D::BOUNDING
)->elementaryTransformed( tf
);
2823 Concrete::Coords2D
llcorner( 0, 0 );
2824 Concrete::Coords2D
urcorner( 0, 0 );
2825 if( ! theBBox
->boundingRectangle( & llcorner
, & urcorner
) )
2827 throw Exceptions::InternalError( "Text mask: The content has no bounding box!" );
2830 RefCountPtr
< SimplePDF::PDF_Stream_out
> form
;
2831 RefCountPtr
< SimplePDF::PDF_Object
> indirection
= SimplePDF::indirect( form
, & Kernel::theIndirectObjectCount
);
2833 RefCountPtr
< SimplePDF::PDF_Resources
> resources
;
2834 (*form
)[ "Resources" ] = SimplePDF::indirect( resources
, & Kernel::theIndirectObjectCount
);
2836 (*form
)[ "Subtype" ] = SimplePDF::newName( "Form" );
2837 (*form
)[ "FormType" ] = SimplePDF::newInt( 1 );
2838 (*form
)[ "BBox" ] = RefCountPtr
< SimplePDF::PDF_Vector
>( new SimplePDF::PDF_Vector( llcorner
.x_
.offtype
< 1, 0 >( ), llcorner
.y_
.offtype
< 1, 0 >( ),
2839 urcorner
.x_
.offtype
< 1, 0 >( ), urcorner
.y_
.offtype
< 1, 0 >( ) ) );
2841 Kernel::PageContentStates
contentState( resources
);
2842 content
->shipout( form
->data
, & contentState
, tf
);
2844 const SimplePDF::PDF_Name
& xoName
= pdfState
->resources_
->nameofXObject( indirection
);
2845 typedef typeof *elements_ ListType
;
2846 for( ListType::const_iterator i
= elements_
->begin( ); i
!= elements_
->end( ); ++i
)
2848 (*i
)->shipout_outlined( os
, pdfState
, tf
, & textMatrix
, & lineMatrix
, & xoName
); /* Passing xoName means "clip". */
2854 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
);
2855 if( ! tf
.isIdentity( ) )
2858 os
<< " cm" << std::endl
;
2861 pdfState
->resources_
->requireProcedureSet( SimplePDF::PDF_Resources::PROC_SET_TEXT
);
2863 os
<< "BT" << std::endl
;
2865 pdfState
->text_
.synchKnockout( os
, textState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
2867 typedef typeof *elements_ ListType
;
2868 for( ListType::const_iterator i
= elements_
->begin( ); i
!= elements_
->end( ); ++i
)
2870 (*i
)->shipout( os
, pdfState
, THE_2D_IDENTITY
, true ); /* true means "clip" */
2872 os
<< "ET" << std::endl
;
2874 content
->shipout( os
, pdfState
, THE_2D_IDENTITY
);
2878 RefCountPtr
< const Lang::ElementaryPath2D
>
2879 Lang::Text::bbox( Lang::Drawable2D::BoxType boxType
) const
2885 Lang::Text::gcMark( Kernel::GCMarkedSet
& marked
)
2887 typedef typeof *elements_ ListType
;
2888 for( ListType::const_iterator i
= elements_
->begin( ); i
!= elements_
->end( ); ++i
)
2890 const_cast< Lang::TextOperation
* >( i
->getPtr( ) )->gcMark( marked
);
2897 RefCountPtr
< const Lang::TransparencyGroup
>
2898 Helpers::newSolidTransparencyGroup( const RefCountPtr
< const Lang::Drawable2D
> & obj2
, const RefCountPtr
< const Lang::Drawable2D
> & obj1
)
2900 return Helpers::newTransparencyGroup( Helpers::newGroup2D( Kernel::THE_DEFAULT_STATE
, obj2
, obj1
),
2903 Lang::THE_INHERITED_COLOR_SPACE
);
2906 RefCountPtr
< const Lang::TransparencyGroup
>
2907 Helpers::newSolidTransparencyGroup( const RefCountPtr
< const Lang::Drawable2D
> & obj3
, const RefCountPtr
< const Lang::Drawable2D
> & obj2
, const RefCountPtr
< const Lang::Drawable2D
> & obj1
)
2909 return Helpers::newTransparencyGroup( Helpers::newGroup2D( Kernel::THE_DEFAULT_STATE
, obj3
, obj2
, obj1
),
2912 Lang::THE_INHERITED_COLOR_SPACE
);
2917 Computation::operator < ( const Computation::UndirectedEdge
& p1
, const Computation::UndirectedEdge
& p2
)
2919 if( p1
.low( ) < p2
.low( ) )
2923 if( p1
.low( ) > p2
.low( ) )
2927 return p1
.high( ) < p2
.high( );