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 RefCountPtr
< const Lang::ElementaryPath2D
> carbbox
= car_
->bbox( boxType
);
164 RefCountPtr
< const Lang::ElementaryPath2D
> cdrbbox
= cdr_
->bbox( boxType
);
166 if( cdrbbox
->empty( ) )
171 Concrete::Length xmin
= Concrete::HUGE_LENGTH
;
172 Concrete::Length xmax
= -Concrete::HUGE_LENGTH
;
173 Concrete::Length ymin
= Concrete::HUGE_LENGTH
;
174 Concrete::Length ymax
= -Concrete::HUGE_LENGTH
;
176 typedef typeof *carbbox PathType
;
177 for( PathType::const_iterator i
= carbbox
->begin( ); i
!= carbbox
->end( ); ++i
)
179 Concrete::Length x
= (*i
)->mid_
->x_
;
180 xmin
= std::min( xmin
, x
);
181 xmax
= std::max( xmax
, x
);
183 Concrete::Length y
= (*i
)->mid_
->y_
;
184 ymin
= std::min( ymin
, y
);
185 ymax
= std::max( ymax
, y
);
188 for( PathType::const_iterator i
= cdrbbox
->begin( ); i
!= cdrbbox
->end( ); ++i
)
190 Concrete::Length x
= (*i
)->mid_
->x_
;
191 xmin
= std::min( xmin
, x
);
192 xmax
= std::max( xmax
, x
);
194 Concrete::Length y
= (*i
)->mid_
->y_
;
195 ymin
= std::min( ymin
, y
);
196 ymax
= std::max( ymax
, y
);
199 Lang::ElementaryPath2D
* res
= new Lang::ElementaryPath2D
;
201 if( xmin
< Concrete::HUGE_LENGTH
)
203 res
->push_back( new Concrete::PathPoint2D( xmin
, ymin
) );
204 res
->push_back( new Concrete::PathPoint2D( xmin
, ymax
) );
205 res
->push_back( new Concrete::PathPoint2D( xmax
, ymax
) );
206 res
->push_back( new Concrete::PathPoint2D( xmax
, ymin
) );
210 return RefCountPtr
< const Lang::ElementaryPath2D
>( res
);
215 Lang::GroupPair2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
217 /* Note the order! Objects are added on the car side of a group being built, so the car side is the "latter".
219 cdr_
->findTags( dst
, dyn
, key
, tf
);
220 car_
->findTags( dst
, dyn
, key
, tf
);
224 Lang::GroupPair2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
227 cdr_
->findOneTag( evalState
, key
, tf
) ||
228 car_
->findOneTag( evalState
, key
, tf
);
231 RefCountPtr
< const Lang::Group2D
>
232 Lang::GroupPair2D::removeShallow( Lang::Symbol::KeyType key
) const
235 typedef const Lang::Tagged2D TaggedType
;
236 TaggedType
* t
= dynamic_cast< TaggedType
* >( car_
.getPtr( ) );
237 if( t
!= 0 && t
->key( ) == key
)
239 return cdr_
->removeShallow( key
);
242 return RefCountPtr
< const Lang::Group2D
>( new Lang::GroupPair2D( car_
, cdr_
->removeShallow( key
), metaState_
) );
246 Lang::GroupPair2D::gcMark( Kernel::GCMarkedSet
& marked
)
248 const_cast< Lang::Drawable2D
* >( car_
.getPtr( ) )->gcMark( marked
);
249 const_cast< Lang::Group2D
* >( cdr_
.getPtr( ) )->gcMark( marked
);
253 Lang::GroupNull2D::GroupNull2D( )
256 Lang::GroupNull2D::~GroupNull2D( )
260 Lang::GroupNull2D::isNull( ) const
265 RefCountPtr
< const Lang::Group2D
>
266 Lang::GroupNull2D::removeShallow( Lang::Symbol::KeyType key
) const
268 return Lang::THE_NULL2D
;
272 Lang::GroupNull2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
275 RefCountPtr
< const Lang::ElementaryPath2D
>
276 Lang::GroupNull2D::bbox( Lang::Drawable2D::BoxType boxType
) const
278 return Lang::THE_EMPTYPATH2D
;
282 Lang::XObject::XObject( const RefCountPtr
< SimplePDF::PDF_Object
> & resource
, const RefCountPtr
< const Lang::ElementaryPath2D
> & boundingbox
)
283 : metaState_( Kernel::THE_NO_STATE
), resource_( resource
), boundingbox_( boundingbox
), bleedbox_( boundingbox
)
286 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
)
287 : metaState_( metaState
), resource_( resource
), boundingbox_( boundingbox
), bleedbox_( bleedbox
)
290 Lang::XObject::~XObject( )
294 Lang::XObject::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
296 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
, false );
297 if( ! tf
.isIdentity( ) )
301 os
<< " cm" << std::endl
;
303 if( metaState_
!= Kernel::THE_NO_STATE
)
305 pdfState
->graphics_
.synchForNonStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
307 os
<< pdfState
->resources_
->nameofXObject( resource_
) << " Do" << std::endl
;
310 RefCountPtr
< SimplePDF::PDF_Object
>
311 Lang::XObject::getResource( ) const
316 RefCountPtr
< const Lang::ElementaryPath2D
>
317 Lang::XObject::bbox( Lang::Drawable2D::BoxType boxType
) const
321 case Lang::Drawable2D::BOUNDING
:
323 case Lang::Drawable2D::BLEED
:
326 throw Exceptions::InternalError( "Lang::XObject::bbox: boxType out of range." );
329 RefCountPtr
< const Lang::XObject
>
330 Lang::XObject::cloneWithState( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
, Concrete::Length bleedMargin
) const
332 Concrete::Coords2D
llcorner( 0, 0 );
333 Concrete::Coords2D
urcorner( 0, 0 );
334 boundingbox_
->boundingRectangle( & llcorner
, & urcorner
);
336 Lang::ElementaryPath2D
* bleedBox
= new Lang::ElementaryPath2D
;
338 bleedBox
->push_back( new Concrete::PathPoint2D( llcorner
.x_
- bleedMargin
, llcorner
.y_
- bleedMargin
) );
339 bleedBox
->push_back( new Concrete::PathPoint2D( urcorner
.x_
+ bleedMargin
, llcorner
.y_
- bleedMargin
) );
340 bleedBox
->push_back( new Concrete::PathPoint2D( urcorner
.x_
+ bleedMargin
, urcorner
.y_
+ bleedMargin
) );
341 bleedBox
->push_back( new Concrete::PathPoint2D( llcorner
.x_
- bleedMargin
, urcorner
.y_
+ bleedMargin
) );
344 return RefCountPtr
< const Lang::XObject
>( new Lang::XObject( resource_
, boundingbox_
, RefCountPtr
< const Lang::ElementaryPath2D
>( bleedBox
), metaState
) );
348 Lang::XObject::setDebugStr( const std::string
& debugStr
)
350 debugStr_
= debugStr
;
354 Lang::XObject::getDebugStr( ) const
360 Lang::XObject::show( std::ostream
& os
) const
362 os
<< "XObject (" << getDebugStr( ) << ")" ;
366 Lang::XObject::gcMark( Kernel::GCMarkedSet
& marked
)
368 // At the time of writing, there is nothing to propagate to.
372 Lang::TransparencyGroup::TransparencyGroup( const RefCountPtr
< SimplePDF::PDF_Indirect_out
> & indirection
, RefCountPtr
< const Lang::ElementaryPath2D
> mybbox
, const RefCountPtr
< const Lang::ColorSpace
> & colorSpace
)
373 : Lang::XObject( indirection
, mybbox
), colorSpace_( colorSpace
), indirection_( indirection
)
376 Lang::TransparencyGroup::~TransparencyGroup( )
379 RefCountPtr
< const Lang::ColorSpace
>
380 Lang::TransparencyGroup::colorSpace( ) const
385 RefCountPtr
< SimplePDF::PDF_Indirect_out
>
386 Lang::TransparencyGroup::getPDF_Object( ) const
388 return indirection_
.unconst_cast
< SimplePDF::PDF_Indirect_out
>( );
391 RefCountPtr
< const Lang::TransparencyGroup
>
392 Helpers::newTransparencyGroup( const RefCountPtr
< const Lang::Drawable2D
> & content
, bool isolated
, bool knockout
, const RefCountPtr
< const Lang::ColorSpace
> & blendSpace
)
394 RefCountPtr
< const Lang::ElementaryPath2D
> theBBox
= content
->bbox( Lang::Drawable2D::BOUNDING
);
395 Concrete::Coords2D
llcorner( 0, 0 );
396 Concrete::Coords2D
urcorner( 0, 0 );
397 if( ! theBBox
->boundingRectangle( & llcorner
, & urcorner
) )
399 throw Exceptions::InternalError( "newTransparencyGroup: The object has no bounding box!" );
402 using namespace Shapes
;
404 RefCountPtr
< SimplePDF::PDF_Stream_out
> form
;
406 (*form
)[ "Subtype" ] = SimplePDF::newName( "Form" );
407 (*form
)[ "FormType" ] = SimplePDF::newInt( 1 );
408 (*form
)[ "BBox" ] = RefCountPtr
< SimplePDF::PDF_Vector
>( new SimplePDF::PDF_Vector( llcorner
.x_
.offtype
< 1, 0 >( ), llcorner
.y_
.offtype
< 1, 0 >( ),
409 urcorner
.x_
.offtype
< 1, 0 >( ), urcorner
.y_
.offtype
< 1, 0 >( ) ) );
410 RefCountPtr
< SimplePDF::PDF_Resources
> resources
;
411 (*form
)[ "Resources" ] = SimplePDF::indirect( resources
, & Kernel::theIndirectObjectCount
);
413 if( ! Kernel::allowTransparency
)
417 else if( ! Kernel::the_PDF_version
.greaterOrEqual( SimplePDF::PDF_Version::PDF_1_4
) )
419 Kernel::the_PDF_version
.message( SimplePDF::PDF_Version::PDF_1_4
, "A transparency group was replaced by a plain XObject." );
423 RefCountPtr
< SimplePDF::PDF_Dictionary
> groupDic
;
424 (*form
)[ "Group" ] = groupDic
;
425 (*groupDic
)[ "S" ] = SimplePDF::newName( "Transparency" );
426 if( ! blendSpace
->isInherent( ) )
428 (*groupDic
)[ "CS" ] = blendSpace
->name( );
432 (*groupDic
)[ "I" ] = SimplePDF::newBoolean( true );
436 (*groupDic
)[ "K" ] = SimplePDF::newBoolean( true );
440 /* There's a possibility of adding a transformation matrix entry in the dictionary here, but it is not used, not even
441 * for transformed drawables.
443 // (*markForm)[ "Matrix" ] = RefCountPtr<PDF_Object>( new PDF_Vector( 1, 0, 0, 1, -30, -30 ) );
445 Kernel::PageContentStates
pdfState( resources
);
446 content
->shipout( form
->data
, & pdfState
, Lang::Transform2D( 1, 0, 0, 1, Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
) );
448 Lang::TransparencyGroup
* res
= new Lang::TransparencyGroup( SimplePDF::indirect( form
, & Kernel::theIndirectObjectCount
),
449 content
->bbox( Lang::Drawable2D::BOUNDING
),
451 res
->setDebugStr( "transparency group" );
452 return RefCountPtr
< const Lang::TransparencyGroup
>( res
);
456 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
)
458 RefCountPtr
< SimplePDF::PDF_Stream_out
> stream
= RefCountPtr
< SimplePDF::PDF_Stream_out
>( new SimplePDF::PDF_Stream_out
);
459 RefCountPtr
< SimplePDF::PDF_Object
> indirection
= SimplePDF::indirect( stream
, & Kernel::theIndirectObjectCount
);
461 (*stream
)[ "Subtype" ] = SimplePDF::newName( "Image" );
462 (*stream
)[ "Width" ] = SimplePDF::newInt( size_x
);
463 (*stream
)[ "Height" ] = SimplePDF::newInt( size_y
);
464 (*stream
)[ "ColorSpace" ] = colorSpace
->name( );
465 (*stream
)[ "BitsPerComponent" ] = SimplePDF::newInt( size_depth
);
467 return new RasterImage( indirection
, size_x
, size_y
, size_depth
, pixelSize_x
, pixelSize_y
, colorSpace
, stream
);
471 Lang::RasterImage::setSoftMask( const RefCountPtr
< const Lang::RasterImage
> & softMask
)
473 /* The caller is responsible for also adding the soft mask under "SMask" in the stream dictionary! */
474 softMask_
= softMask
;
477 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
)
478 : Lang::XObject( resource
, RefCountPtr
< const Lang::ElementaryPath2D
>( newBoundingBox( size_x
, size_y
, pixelSize_x
, pixelSize_y
) ) ),
479 size_x_( size_x
), size_y_( size_y
), size_depth_( size_depth
), pixelSize_x_( pixelSize_x
), pixelSize_y_( pixelSize_y
), colorSpace_( colorSpace
),
480 softMask_( NullPtr
< const Lang::RasterImage
>( ) ),
484 Lang::ElementaryPath2D
*
485 Lang::RasterImage::newBoundingBox( size_t size_x
, size_t size_y
, Concrete::Length pixelSize_x
, Concrete::Length pixelSize_y
)
487 /* Note that this bounding box assumes that the image is scaled to resolution during shipout. */
488 Lang::ElementaryPath2D
* res
= new Lang::ElementaryPath2D
;
490 res
->push_back( new Concrete::PathPoint2D( Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
) );
491 res
->push_back( new Concrete::PathPoint2D( size_x
* pixelSize_x
, Concrete::ZERO_LENGTH
) );
492 res
->push_back( new Concrete::PathPoint2D( size_x
* pixelSize_x
, size_y
* pixelSize_y
) );
493 res
->push_back( new Concrete::PathPoint2D( Concrete::ZERO_LENGTH
, size_y
* pixelSize_y
) );
498 Lang::RasterImage::~RasterImage( )
501 RefCountPtr
< const Lang::Class
> Lang::RasterImage::TypeID( new Lang::SystemFinalClass( strrefdup( "RasterImage" ) ) );
502 TYPEINFOIMPL( RasterImage
);
505 Lang::RasterImage::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
507 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_
) ),
508 Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
) ) );
511 Kernel::VariableHandle
512 Lang::RasterImage::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
514 if( strcmp( fieldID
, "size_x" ) == 0 )
516 return Helpers::newValHandle( new Lang::Integer( size_x_
) );
518 if( strcmp( fieldID
, "size_y" ) == 0 )
520 return Helpers::newValHandle( new Lang::Integer( size_y_
) );
522 if( strcmp( fieldID
, "depth" ) == 0 )
524 return Helpers::newValHandle( new Lang::Integer( size_depth_
) );
526 if( strcmp( fieldID
, "space" ) == 0 )
528 return Kernel::VariableHandle( new Kernel::Variable( colorSpace_
) );
530 throw Exceptions::NonExistentMember( getTypeName( ), fieldID
);
534 Lang::RasterImage::gcMark( Kernel::GCMarkedSet
& marked
)
536 const_cast< Lang::ColorSpace
* >( colorSpace_
.getPtr( ) )->gcMark( marked
);
537 if( softMask_
!= NullPtr
< const Lang::RasterImage
>( ) )
539 const_cast< Lang::RasterImage
* >( softMask_
.getPtr( ) )->gcMark( marked
);
541 Lang::XObject::gcMark( marked
);
546 Lang::PaintedPath2D::PaintedPath2D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
,
547 const char * paintCmd
)
548 : metaState_( metaState
), paintCmd_( paintCmd
)
551 Lang::PaintedPath2D::PaintedPath2D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
,
552 RefCountPtr
< const Lang::ElementaryPath2D
> path
,
553 const char * paintCmd
)
554 : metaState_( metaState
), paintCmd_( paintCmd
)
559 Lang::PaintedPath2D::PaintedPath2D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
,
560 RefCountPtr
< const Lang::MultiPath2D
> paths
,
561 const char * paintCmd
)
562 : metaState_( metaState
), paintCmd_( paintCmd
)
564 for( Lang::MultiPath2D::const_iterator i
= paths
->begin( ); i
!= paths
->end( ); ++i
)
567 typedef const Lang::ElementaryPath2D ArgType
;
568 RefCountPtr
< ArgType
> subpath
= (*i
).down_cast
< ArgType
>( );
569 if( subpath
!= NullPtr
< ArgType
>( ) )
571 addSubPath( subpath
);
577 typedef const Lang::CompositePath2D ArgType
;
578 ArgType
* subpath
= dynamic_cast< ArgType
* >( (*i
).getPtr( ) );
581 addSubPath( subpath
->getElementaryPath( ) );
585 throw Exceptions::InternalError( "Painting 2D path: Encountered a subpath of unexpected type" );
589 Lang::PaintedPath2D::~PaintedPath2D( )
592 RefCountPtr
< const Lang::Class
> Lang::PaintedPath2D::TypeID( new Lang::SystemFinalClass( strrefdup( "PaintedPath2D" ) ) );
593 TYPEINFOIMPL( PaintedPath2D
);
596 Lang::PaintedPath2D::addSubPath( RefCountPtr
< const Lang::ElementaryPath2D
> subpath
)
598 path_
.push_back( subpath
);
602 Lang::PaintedPath2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
604 /* Transforming the path by tf is not good enough, since that does not transform softmasks etc.
608 strcpy( pdfCmd
, paintCmd_
);
610 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
, false );
611 if( ! tf
.isIdentity( ) )
615 os
<< " cm" << std::endl
;
617 if( strcmp( paintCmd_
, "S" ) == 0 )
619 pdfState
->graphics_
.synchForStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
621 else if( strcmp( paintCmd_
, "f" ) == 0 ||
622 strcmp( paintCmd_
, "f*" ) == 0 )
624 pdfState
->graphics_
.synchForNonStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
626 else if( strcmp( paintCmd_
, "B" ) == 0 ||
627 strcmp( paintCmd_
, "B*" ) == 0 ||
628 strcmp( paintCmd_
, "b" ) == 0 ||
629 strcmp( paintCmd_
, "b*" ) == 0 )
631 pdfState
->graphics_
.synchForNonStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
632 pdfState
->graphics_
.synchForStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
634 else if( strcmp( paintCmd_
, "E" ) == 0 ||
635 strcmp( paintCmd_
, "E*" ) == 0 ||
636 strcmp( paintCmd_
, "e" ) == 0 ||
637 strcmp( paintCmd_
, "e*" ) == 0 )
639 pdfCmd
[0] += 'B' - 'E';
640 // Note that this is my own interpretation; usually, the stroke is made with the stroking color,
641 // but I use this to make filled regions just a little bit bigger, and then it is the nonstroking
642 // color that shall be applied to the stroke as well.
643 pdfState
->graphics_
.synchForNonStroke( os
, metaState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
644 pdfState
->graphics_
.synchStrokingColorWithNonStrokingColor( os
, pdfState
->resources_
.getPtr( ), Concrete::ZERO_LENGTH
);
648 throw Exceptions::InternalError( "Unexpected paintCmd in PaintedPath2D::shipout" );
651 typedef typeof path_ ListType
;
652 for( ListType::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
654 (*i
)->writePath( os
);
656 os
<< " " << pdfCmd
<< std::endl
;
659 RefCountPtr
< const Lang::ElementaryPath2D
>
660 Lang::PaintedPath2D::bbox( Lang::Drawable2D::BoxType boxType
) const
664 return RefCountPtr
< const Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D
);
667 Concrete::Length xmin
= Concrete::HUGE_LENGTH
;
668 Concrete::Length xmax
= -Concrete::HUGE_LENGTH
;
669 Concrete::Length ymin
= Concrete::HUGE_LENGTH
;
670 Concrete::Length ymax
= -Concrete::HUGE_LENGTH
;
672 Concrete::Coords2D
llcorner( 0, 0 ); /* Temporary variables to be used in the loop below. */
673 Concrete::Coords2D
urcorner( 0, 0 );
675 typedef typeof path_ PathType
;
676 for( PathType::const_iterator j
= path_
.begin( ); j
!= path_
.end( ); ++j
)
678 if( (*j
)->boundingRectangle( & llcorner
, & urcorner
) )
681 xmin
= std::min( xmin
, llcorner
.x_
);
682 xmax
= std::max( xmax
, urcorner
.x_
);
683 ymin
= std::min( ymin
, llcorner
.y_
);
684 ymax
= std::max( ymax
, urcorner
.y_
);
688 Lang::ElementaryPath2D
* res
= new Lang::ElementaryPath2D
;
690 if( xmin
< Concrete::HUGE_LENGTH
)
692 if( toupper( *paintCmd_
) == 'S' ||
693 toupper( *paintCmd_
) == 'B' )
695 xmin
-= 0.5 * metaState_
->width_
;
696 ymin
-= 0.5 * metaState_
->width_
;
697 xmax
+= 0.5 * metaState_
->width_
;
698 ymax
+= 0.5 * metaState_
->width_
;
700 res
->push_back( new Concrete::PathPoint2D( xmin
, ymin
) );
701 res
->push_back( new Concrete::PathPoint2D( xmin
, ymax
) );
702 res
->push_back( new Concrete::PathPoint2D( xmax
, ymax
) );
703 res
->push_back( new Concrete::PathPoint2D( xmax
, ymin
) );
707 return RefCountPtr
< const Lang::ElementaryPath2D
>( res
);
711 Lang::PaintedPath2D::gcMark( Kernel::GCMarkedSet
& marked
)
715 Lang::Transformed2D::Transformed2D( RefCountPtr
< const Lang::Drawable2D
> element
, const Lang::Transform2D
& mytf
)
716 : mytf_( mytf
), element_( element
)
719 Lang::Transformed2D::~Transformed2D( )
723 Lang::Transformed2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
725 element_
->shipout( os
, pdfState
, Lang::Transform2D( tf
, mytf_
) );
728 RefCountPtr
< const Lang::ElementaryPath2D
>
729 Lang::Transformed2D::bbox( Lang::Drawable2D::BoxType boxType
) const
731 return element_
->bbox( boxType
)->elementaryTransformed( mytf_
);
735 Lang::Transformed2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
737 element_
->findTags( dst
, dyn
, key
, Lang::Transform2D( tf
, mytf_
) );
741 Lang::Transformed2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
744 element_
->findOneTag( evalState
, key
, Lang::Transform2D( tf
, mytf_
) );
748 Lang::Transformed2D::gcMark( Kernel::GCMarkedSet
& marked
)
750 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
754 Lang::BBoxed2D::BBoxed2D( RefCountPtr
< const Lang::Drawable2D
> element
, RefCountPtr
< const Lang::ElementaryPath2D
> mybbox
, BoxType boxType
)
755 : Lang::PaintedPolygon2D( Kernel::THE_NO_STATE
, mybbox
), mybbox_( mybbox
), element_( element
), boxType_( boxType
)
758 Lang::BBoxed2D::~BBoxed2D( )
762 Lang::BBoxed2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
764 /* At the moment, we don't clip according to the bbox, we only lie about our size.
766 element_
->shipout( os
, pdfState
, tf
);
769 RefCountPtr
< const Lang::ElementaryPath2D
>
770 Lang::BBoxed2D::bbox( Lang::Drawable2D::BoxType boxType
) const
773 || ( boxType
== Lang::Drawable2D::BOUNDING
&& boxType_
== BOUNDING
)
774 || ( boxType
== Lang::Drawable2D::BLEED
&& boxType_
== BLEED
) )
778 return element_
->bbox( boxType
);
782 Lang::BBoxed2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
784 element_
->findTags( dst
, dyn
, key
, tf
);
788 Lang::BBoxed2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
791 element_
->findOneTag( evalState
, key
, tf
);
795 Lang::BBoxed2D::gcMark( Kernel::GCMarkedSet
& marked
)
797 Lang::PaintedPolygon2D::gcMark( marked
);
798 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
802 Lang::Clipped2D::Clipped2D( const RefCountPtr
< const Lang::Drawable2D
> & element
, const char * clipCommand
)
803 : element_( element
), clipCommand_( clipCommand
)
806 Lang::Clipped2D::~Clipped2D( )
810 Lang::Clipped2D::addSubPath( const RefCountPtr
< const Lang::ElementaryPath2D
> & subpath
)
812 clipList_
.push_back( subpath
);
816 Lang::Clipped2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
818 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
);
819 if( ! tf
.isIdentity( ) )
822 os
<< " cm" << std::endl
;
824 typedef typeof clipList_ ListType
;
825 for( ListType::const_iterator i
= clipList_
.begin( ); i
!= clipList_
.end( ); ++i
)
827 (*i
)->writePath( os
);
829 os
<< " " << clipCommand_
<< " n" << std::endl
;
830 element_
->shipout( os
, pdfState
, THE_2D_IDENTITY
);
833 RefCountPtr
< const Lang::ElementaryPath2D
>
834 Lang::Clipped2D::bbox( Lang::Drawable2D::BoxType boxType
) const
836 RefCountPtr
< const Lang::ElementaryPath2D
> elem_bbox
= element_
->bbox( boxType
);
838 if( clipList_
.empty( ) )
840 return RefCountPtr
< const Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D
);
843 Concrete::Coords2D
llElemBbox( 0, 0 );
844 Concrete::Coords2D
urElemBbox( 0, 0 );
845 elem_bbox
->boundingRectangle( & llElemBbox
, & urElemBbox
);
847 Concrete::Length xmin
= Concrete::HUGE_LENGTH
;
848 Concrete::Length xmax
= -Concrete::HUGE_LENGTH
;
849 Concrete::Length ymin
= Concrete::HUGE_LENGTH
;
850 Concrete::Length ymax
= -Concrete::HUGE_LENGTH
;
852 Concrete::Coords2D
llcorner( 0, 0 ); /* Temporary variables to be used in the loop below. */
853 Concrete::Coords2D
urcorner( 0, 0 );
855 typedef typeof clipList_ PathType
;
856 for( PathType::const_iterator j
= clipList_
.begin( ); j
!= clipList_
.end( ); ++j
)
858 if( (*j
)->boundingRectangle( & llcorner
, & urcorner
) )
861 xmin
= std::min( xmin
, llcorner
.x_
);
862 xmax
= std::max( xmax
, urcorner
.x_
);
863 ymin
= std::min( ymin
, llcorner
.y_
);
864 ymax
= std::max( ymax
, urcorner
.y_
);
868 xmin
= std::max( xmin
, llElemBbox
.x_
);
869 ymin
= std::max( ymin
, llElemBbox
.y_
);
870 xmax
= std::min( xmax
, urElemBbox
.x_
);
871 ymax
= std::min( ymax
, urElemBbox
.y_
);
873 Lang::ElementaryPath2D
* res
= new Lang::ElementaryPath2D
;
875 if( xmin
< xmax
&& ymin
< ymax
)
877 res
->push_back( new Concrete::PathPoint2D( xmin
, ymin
) );
878 res
->push_back( new Concrete::PathPoint2D( xmin
, ymax
) );
879 res
->push_back( new Concrete::PathPoint2D( xmax
, ymax
) );
880 res
->push_back( new Concrete::PathPoint2D( xmax
, ymin
) );
884 return RefCountPtr
< const Lang::ElementaryPath2D
>( res
);
888 Lang::Clipped2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
890 element_
->findTags( dst
, dyn
, key
, tf
);
894 Lang::Clipped2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
897 element_
->findOneTag( evalState
, key
, tf
);
901 Lang::Clipped2D::gcMark( Kernel::GCMarkedSet
& marked
)
903 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
906 RefCountPtr
< const Lang::Drawable2D
>
907 Lang::Clipped2D::debugPolys( ) const
909 Kernel::GraphicsState
* frameStatePtr
= new Kernel::GraphicsState( true );
910 frameStatePtr
->width_
= Concrete::Length( 0.2 );
911 RefCountPtr
< const Kernel::GraphicsState
> frameState( frameStatePtr
);
913 Lang::PaintedPath2D
* res
= new Lang::PaintedPath2D( frameState
, "S" );
914 typedef typeof clipList_ ListType
;
915 for( ListType::const_iterator i
= clipList_
.begin( ); i
!= clipList_
.end( ); ++i
)
917 res
->addSubPath( *i
);
920 return RefCountPtr
< const Lang::Drawable2D
>( res
);
924 Lang::Clipped2D::isSingleConvexPoly( Concrete::Length tol
) const
926 if( clipList_
.size( ) != 1 )
930 return clipList_
.front( )->isConvexPoly( tol
);
934 Lang::Clipped2D::convexPolyContains( const Concrete::Coords2D
& p
, Concrete::Length tol
) const
936 return clipList_
.front( )->convexPolyContains( p
, tol
);
939 Lang::SoftMasked2D::SoftMasked2D( const RefCountPtr
< const Lang::Drawable2D
> & element
, const RefCountPtr
< const Lang::SoftMask
> & mask
)
940 : element_( element
), mask_( mask
)
943 Lang::SoftMasked2D::~SoftMasked2D( )
947 Lang::SoftMasked2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
949 const SimplePDF::PDF_Version::Version SOFTMASK_VERSION
= SimplePDF::PDF_Version::PDF_1_4
;
950 if( Kernel::the_PDF_version
.greaterOrEqual( SOFTMASK_VERSION
) )
952 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
);
953 if( ! tf
.isIdentity( ) )
956 os
<< " cm" << std::endl
;
958 os
<< pdfState
->resources_
->nameofGraphicsState( mask_
->graphicsStateResource_
) << " gs " << std::endl
;
959 element_
->shipout( os
, pdfState
, THE_2D_IDENTITY
);
963 Kernel::the_PDF_version
.message( SOFTMASK_VERSION
, "A soft mask was ignored." );
964 element_
->shipout( os
, pdfState
, tf
);
968 RefCountPtr
< const Lang::ElementaryPath2D
>
969 Lang::SoftMasked2D::bbox( Lang::Drawable2D::BoxType boxType
) const
971 return element_
->bbox( boxType
);
975 Lang::SoftMasked2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
977 element_
->findTags( dst
, dyn
, key
, tf
);
981 Lang::SoftMasked2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
984 element_
->findOneTag( evalState
, key
, tf
);
988 Lang::SoftMasked2D::gcMark( Kernel::GCMarkedSet
& marked
)
990 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
991 const_cast< Lang::SoftMask
* >( mask_
.getPtr( ) )->gcMark( marked
);
995 Lang::TextMasked2D::TextMasked2D( const RefCountPtr
< const Lang::Drawable2D
> & element
, const RefCountPtr
< const Lang::Text
> & mask
)
996 : element_( element
), mask_( mask
)
999 Lang::TextMasked2D::~TextMasked2D( )
1003 Lang::TextMasked2D::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
1005 mask_
->shipout_clip( os
, pdfState
, tf
, element_
);
1008 RefCountPtr
< const Lang::ElementaryPath2D
>
1009 Lang::TextMasked2D::bbox( Lang::Drawable2D::BoxType boxType
) const
1011 return mask_
->bbox( boxType
);
1015 Lang::TextMasked2D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
1017 element_
->findTags( dst
, dyn
, key
, tf
);
1021 Lang::TextMasked2D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform2D
& tf
) const
1024 element_
->findOneTag( evalState
, key
, tf
);
1028 Lang::TextMasked2D::gcMark( Kernel::GCMarkedSet
& marked
)
1030 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
1031 const_cast< Lang::Text
* >( mask_
.getPtr( ) )->gcMark( marked
);
1035 Lang::Drawable3D::Drawable3D( )
1038 Lang::Drawable3D::~Drawable3D( )
1041 RefCountPtr
< const Lang::Transformed3D
>
1042 Lang::Drawable3D::typed_transformed( const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1044 return RefCountPtr
< const Lang::Transformed3D
>( new Lang::Transformed3D( self
, tf
) );
1047 RefCountPtr
< const Lang::Geometric3D
>
1048 Lang::Drawable3D::transformed( const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Geometric3D
> & self
) const
1050 return typed_transformed( tf
, self
.down_cast
< const Lang::Drawable3D
>( ) );
1053 RefCountPtr
< const Lang::Geometric2D
>
1054 Lang::Drawable3D::to2D( const Kernel::PassedDyn
& dyn
, const RefCountPtr
< const Lang::Geometric3D
> & self
) const
1056 typedef const Lang::Drawable3D SelfType
;
1057 RefCountPtr
< SelfType
> typedSelf
= self
.down_cast
< SelfType
>( );
1058 if( typedSelf
== NullPtr
< SelfType
>( ) )
1060 throw Exceptions::InternalError( "The self-value passed to Drawable3D::to2D was of bad type." );
1062 return typed_to2D( dyn
, Lang::THE_3D_IDENTITY
, typedSelf
);
1066 Lang::Drawable3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1068 // Not overloading this methods means that there are no tagged objects within this.
1072 Lang::Drawable3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1074 // Not overloading this methods means that there are no tagged objects within this.
1079 Lang::Drawable3D::gcMark( Kernel::GCMarkedSet
& marked
)
1082 RefCountPtr
< const Lang::Class
> Lang::Drawable3D::TypeID
= NullPtr
< const Lang::Class
>( ); /* The value is set in main */
1083 TYPEINFOIMPL( Drawable3D
);
1084 DISPATCHIMPL( Drawable3D
);
1087 Lang::Group3D::Group3D( )
1090 Lang::Group3D::~Group3D( )
1093 RefCountPtr
< const Lang::Drawable2D
>
1094 Lang::Group3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1096 return group_to2D( dyn
, tf
);
1100 RefCountPtr
< const Lang::Class
> Lang::Group3D::TypeID( new Lang::SystemFinalClass( strrefdup( "Group3D" ) ) );
1101 TYPEINFOIMPL( Group3D
);
1103 RefCountPtr
< const Lang::Group3D
>
1104 Helpers::newGroup3D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
, const RefCountPtr
< const Lang::Drawable3D
> & obj2
, const RefCountPtr
< const Lang::Drawable3D
> & obj1
)
1106 RefCountPtr
< const Lang::Group3D
> res
= Lang::THE_NULL3D
;
1107 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj1
,
1110 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj2
,
1116 RefCountPtr
< const Lang::Group3D
>
1117 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
)
1119 RefCountPtr
< const Lang::Group3D
> res
= Lang::THE_NULL3D
;
1120 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj1
,
1123 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj2
,
1126 res
= RefCountPtr
< const Lang::GroupPair3D
>( new Lang::GroupPair3D( obj3
,
1133 Lang::GroupPair3D::GroupPair3D( const RefCountPtr
< const Lang::Drawable3D
> & car
, const RefCountPtr
< const Lang::Group3D
> & cdr
, const RefCountPtr
< const Kernel::GraphicsState
> & metaState
)
1134 : metaState_( metaState
), car_( car
), cdr_( cdr
)
1137 Lang::GroupPair3D::~GroupPair3D( )
1141 Lang::GroupPair3D::isNull( ) const
1146 RefCountPtr
< const Lang::Group2D
>
1147 Lang::GroupPair3D::group_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
) const
1149 return RefCountPtr
< const Lang::Group2D
>( new Lang::GroupPair2D( car_
->typed_to2D( dyn
, tf
, car_
),
1150 cdr_
->group_to2D( dyn
, tf
),
1155 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
1157 car_
->polygonize( zBufPile
, linePile
, dyn
, tf
, car_
);
1158 cdr_
->polygonize( zBufPile
, linePile
, dyn
, tf
, cdr_
);
1162 Lang::GroupPair3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1164 /* See note on order in GroupPair2D!
1166 cdr_
->findTags( dst
, dyn
, key
, tf
);
1167 car_
->findTags( dst
, dyn
, key
, tf
);
1171 Lang::GroupPair3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1174 cdr_
->findOneTag( evalState
, key
, tf
) ||
1175 car_
->findOneTag( evalState
, key
, tf
);
1178 RefCountPtr
< const Lang::Group3D
>
1179 Lang::GroupPair3D::removeShallow( Lang::Symbol::KeyType key
) const
1182 typedef const Lang::Tagged3D TaggedType
;
1183 TaggedType
* t
= dynamic_cast< TaggedType
* >( car_
.getPtr( ) );
1184 if( t
!= 0 && t
->key( ) == key
)
1186 return cdr_
->removeShallow( key
);
1189 return RefCountPtr
< const Lang::Group3D
>( new Lang::GroupPair3D( car_
, cdr_
->removeShallow( key
), metaState_
) );
1193 Lang::GroupPair3D::gcMark( Kernel::GCMarkedSet
& marked
)
1195 const_cast< Lang::Drawable3D
* >( car_
.getPtr( ) )->gcMark( marked
);
1196 const_cast< Lang::Group3D
* >( cdr_
.getPtr( ) )->gcMark( marked
);
1200 Lang::GroupNull3D::GroupNull3D( )
1203 Lang::GroupNull3D::~GroupNull3D( )
1207 Lang::GroupNull3D::isNull( ) const
1212 RefCountPtr
< const Lang::Group3D
>
1213 Lang::GroupNull3D::removeShallow( Lang::Symbol::KeyType key
) const
1215 return Lang::THE_NULL3D
;
1218 RefCountPtr
< const Lang::Group2D
>
1219 Lang::GroupNull3D::group_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
) const
1221 return Lang::THE_NULL2D
;
1225 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
1229 Lang::Drawable2Din3D::Drawable2Din3D( RefCountPtr
< const Lang::Drawable2D
> element
)
1230 : element_( element
)
1233 Lang::Drawable2Din3D::~Drawable2Din3D( )
1236 RefCountPtr
< const Lang::Drawable2D
>
1237 Lang::Drawable2Din3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1239 Concrete::Length eyez
= dyn
->getEyeZ( );
1240 if( eyez
< Concrete::HUGE_LENGTH
)
1242 std::ostringstream msg
;
1243 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." ;
1244 throw Exceptions::MiscellaneousRequirement( strrefdup( msg
.str( ).c_str( ) ) );
1247 // The transform in 2D is obtained by setting z = 0 in the source 3D coordinates, and omitting the z-coordinate in the new coordinates
1249 return RefCountPtr
< const Lang::Drawable2D
>( new Lang::Transformed2D( element_
, Lang::Transform2D( tf
.xx_
, tf
.yx_
, tf
.xy_
, tf
.yy_
, tf
.xt_
, tf
.yt_
) ) );
1253 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
1255 throw Exceptions::NotImplemented( "Triangularization of immersed objects." );
1259 Lang::Drawable2Din3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1261 Concrete::Length eyez
= dyn
->getEyeZ( );
1262 if( eyez
< Concrete::HUGE_LENGTH
)
1264 std::ostringstream msg
;
1265 msg
<< "Tags in an immersed object are not accessible from a finite viewing distance. Consider using facing rather than immerse." ;
1266 throw Exceptions::MiscellaneousRequirement( strrefdup( msg
.str( ).c_str( ) ) );
1269 // The transform in 2D is obtained by setting z = 0 in the source 3D coordinates, and omitting the z-coordinate in the new coordinates
1271 element_
->findTags( dst
, dyn
, key
, Lang::Transform2D( tf
.xx_
, tf
.yx_
, tf
.xy_
, tf
.yy_
, tf
.xt_
, tf
.yt_
) );
1275 Lang::Drawable2Din3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1277 Concrete::Length eyez
= evalState
->dyn_
->getEyeZ( );
1278 if( eyez
< Concrete::HUGE_LENGTH
)
1280 std::ostringstream msg
;
1281 msg
<< "Tags in an immersed object are not accessible from a finite viewing distance. Consider using facing rather than immerse." ;
1282 throw Exceptions::MiscellaneousRequirement( strrefdup( msg
.str( ).c_str( ) ) );
1285 // The transform in 2D is obtained by setting z = 0 in the source 3D coordinates, and omitting the z-coordinate in the new coordinates
1288 element_
->findOneTag( evalState
, key
, Lang::Transform2D( tf
.xx_
, tf
.yx_
, tf
.xy_
, tf
.yy_
, tf
.xt_
, tf
.yt_
) );
1292 Lang::Drawable2Din3D::gcMark( Kernel::GCMarkedSet
& marked
)
1294 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
1299 Lang::Facing2Din3D::Facing2Din3D( RefCountPtr
< const Lang::Drawable2D
> element
, bool scale
, bool distort
)
1300 : element_( element
), scale_( scale
), distort_( distort
)
1303 Lang::Facing2Din3D::~Facing2Din3D( )
1306 RefCountPtr
< const Lang::Drawable2D
>
1307 Lang::Facing2Din3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1309 Concrete::Length eyez
= dyn
->getEyeZ( );
1311 if( scale_
&& eyez
< Concrete::HUGE_LENGTH
)
1313 s
= eyez
/ ( eyez
- tf
.zt_
);
1318 if( eyez
< Concrete::HUGE_LENGTH
)
1320 x
= tf
.xt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1321 y
= tf
.yt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1331 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
) ) );
1335 return RefCountPtr
< const Lang::Drawable2D
>( new Lang::Transformed2D( element_
, Lang::Transform2D( s
, 0, 0, s
, x
, y
) ) );
1340 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
1342 throw Exceptions::MiscellaneousRequirement( "Facing objects cannot be polygonized." );
1346 Lang::Facing2Din3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1348 Concrete::Length eyez
= dyn
->getEyeZ( );
1350 if( scale_
&& eyez
< Concrete::HUGE_LENGTH
)
1352 s
= eyez
/ ( eyez
- tf
.zt_
);
1357 if( eyez
< Concrete::HUGE_LENGTH
)
1359 x
= tf
.xt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1360 y
= tf
.yt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1370 element_
->findTags( dst
, dyn
, key
, Lang::Transform2D( s
* tf
.xx_
, s
* tf
.yx_
, s
* tf
.xy_
, s
* tf
.yy_
, x
, y
) );
1374 element_
->findTags( dst
, dyn
, key
, Lang::Transform2D( s
, 0, 0, s
, x
, y
) );
1379 Lang::Facing2Din3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1381 Concrete::Length eyez
= evalState
->dyn_
->getEyeZ( );
1383 if( scale_
&& eyez
< Concrete::HUGE_LENGTH
)
1385 s
= eyez
/ ( eyez
- tf
.zt_
);
1390 if( eyez
< Concrete::HUGE_LENGTH
)
1392 x
= tf
.xt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1393 y
= tf
.yt_
* ( eyez
/ ( eyez
- tf
.zt_
) );
1404 element_
->findOneTag( evalState
, key
, Lang::Transform2D( s
* tf
.xx_
, s
* tf
.yx_
, s
* tf
.xy_
, s
* tf
.yy_
, x
, y
) );
1409 element_
->findOneTag( evalState
, key
, Lang::Transform2D( s
, 0, 0, s
, x
, y
) );
1414 Lang::Facing2Din3D::gcMark( Kernel::GCMarkedSet
& marked
)
1416 const_cast< Lang::Drawable2D
* >( element_
.getPtr( ) )->gcMark( marked
);
1420 Lang::FacingFunction3D::FacingFunction3D( Kernel::PassedDyn dyn
, RefCountPtr
< const Lang::Function
> generator
)
1421 : dyn_( dyn
), generator_( generator
)
1424 Lang::FacingFunction3D::~FacingFunction3D( )
1427 RefCountPtr
< const Lang::Drawable2D
>
1428 Lang::FacingFunction3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
1430 /* Too bad we can't call the function CPP here...
1432 Kernel::ValueRef valUntyped
= NullPtr
< const Lang::Value
>( );
1434 static Ast::SourceLocation
loc( Ast::FileID::build_internal( "<Facing a function in 3D>" ) );
1436 /* Note that the use of a StoreValueContinuation relies on valUntyped being alive at the time the continuation is invoked.
1439 Kernel::EvalState
evalState( 0,
1442 Kernel::ContRef( new Kernel::StoreValueContinuation( & valUntyped
,
1443 Kernel::ContRef( new Kernel::ExitContinuation( & done
, loc
) ),
1446 generator_
->call( & evalState
, RefCountPtr
< const Lang::Value
>( new Lang::Transform3D( tf
) ), loc
);
1450 evalState
.expr_
->eval( & evalState
);
1453 return Helpers::down_cast
< const Lang::Drawable2D
>( valUntyped
, loc
);
1457 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
1459 throw Exceptions::MiscellaneousRequirement( "Facing functions cannot be polygonized." );
1463 Lang::FacingFunction3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1466 * At the moment, we don't search facing functions for tags!
1471 Lang::FacingFunction3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
1474 * At the moment, we don't search facing functions for tags!
1480 Lang::FacingFunction3D::gcMark( Kernel::GCMarkedSet
& marked
)
1482 const_cast< Lang::Function
* >( generator_
.getPtr( ) )->gcMark( marked
);
1486 Computation::PaintedPolygon3D::PaintedPolygon3D( bool singleSided
, const Concrete::UnitFloatTriple
& normal
, Concrete::Length m
, Concrete::Length tiebreaker
)
1487 : singleSided_( singleSided
), normal_( normal
), m_( m
), tiebreaker_( tiebreaker
)
1490 Computation::PaintedPolygon3D::~PaintedPolygon3D( )
1494 Computation::PaintedPolygon3D::pushPoint( const Concrete::Coords3D
& p
)
1496 Concrete::Length tmp
= Concrete::inner( normal_
, p
) - m_
;
1497 if( tmp
.abs( ) > Computation::theTrixelizeSplicingTol
)
1499 std::ostringstream msg
;
1500 msg
<< "The 3D painted path was not flat enough (" << tmp
.offtype
< 1, 0 >( ) << " > splicingtol) to make a polygon." ;
1501 throw Exceptions::OutOfRange( strrefdup( msg
) );
1503 points_
.push_back( p
);
1507 Computation::PaintedPolygon3D::push_zBufTriangles( const Lang::Transform3D
& tf
, const Concrete::Length eyez
, std::list
< Computation::ZBufTriangle
> * triangleQueue
, bool respectSingleSided
) const
1509 // This function shall not push tiny triangles!
1511 // Note that the ZBufTriangles pushed are not completely transformed, since *this is the painter, and not transformed by tf.
1512 // The ugly solution to this is that tf must also be specified when painting the area.
1514 if( points_
.size( ) < 3 )
1519 // At the moment, convexity is assumed!
1521 typedef Computation::ZBufTriangle::ZMap ZMapType
;
1522 if( tf
.isIdentity( ) )
1524 if( respectSingleSided
&& singleSided_
)
1526 const Concrete::Coords3D
& somePoint
= points_
.front( );
1527 if( normal_
.z_
* eyez
- Concrete::inner( normal_
, somePoint
) <= 0 )
1533 RefCountPtr
< const ZMapType
> zMap( new ZMapType( normal_
, m_
, tiebreaker_
, eyez
) );
1534 typedef typeof points_ ListType
;
1535 ListType::const_iterator i
= points_
.begin( );
1536 Concrete::Coords2D p0
= i
->make2DAutomatic( eyez
);
1538 Concrete::Coords2D p1
= i
->make2DAutomatic( eyez
);
1540 for( ; i
!= points_
.end( ); ++i
)
1542 Concrete::Coords2D p2
= i
->make2DAutomatic( eyez
);
1543 // This tolerance test assures that we don't produce tiny-tiny triangles. It is an inscribed circle test.
1544 if( Computation::triangleArea( p0
, p1
, p2
) > Computation::theTrixelizeOverlapTol
* Computation::triangleSemiPerimeter( p0
, p1
, p2
) )
1546 triangleQueue
->push_back( Computation::ZBufTriangle( this,
1555 RefCountPtr
< const ZMapType
> zMap
= RefCountPtr
< const ZMapType
>( NullPtr
< const ZMapType
>( ) );
1557 Concrete::UnitFloatTriple Tnormal
= tf
.transformPlaneUnitNormal( normal_
);
1558 if( respectSingleSided
&& singleSided_
)
1560 const Concrete::Coords3D
& somePoint
= points_
.front( );
1561 if( Tnormal
.z_
* eyez
- Concrete::inner( Tnormal
, somePoint
.transformed( tf
) ) <= 0 )
1567 double ax
= fabs( normal_
.x_
);
1568 double ay
= fabs( normal_
.y_
);
1569 double az
= fabs( normal_
.z_
);
1570 Concrete::Coords3D
x0( 0, 0, 0 );
1571 if( ax
>= ay
&& ax
>= az
)
1573 x0
= Concrete::Coords3D( m_
/ normal_
.x_
, 0, 0 );
1577 x0
= Concrete::Coords3D( 0, m_
/ normal_
.y_
, 0 );
1581 x0
= Concrete::Coords3D( 0, 0, m_
/ normal_
.z_
);
1583 Concrete::Length Tm
= Concrete::inner( Tnormal
, x0
.transformed( tf
) );
1585 zMap
= RefCountPtr
< const ZMapType
>( new ZMapType( Tnormal
, Tm
, tiebreaker_
, eyez
) );
1589 typedef typeof points_ ListType
;
1590 ListType::const_iterator i
= points_
.begin( );
1591 Concrete::Coords2D p0
= i
->transformed( tf
).make2DAutomatic( eyez
);
1593 Concrete::Coords2D p1
= i
->transformed( tf
).make2DAutomatic( eyez
);
1595 for( ; i
!= points_
.end( ); ++i
)
1597 Concrete::Coords2D p2
= i
->transformed( tf
).make2DAutomatic( eyez
);
1598 // This tolerance test assures that we don't produce tiny-tiny triangles. It is an inscribed circle test.
1599 if( Computation::triangleArea( p0
, p1
, p2
) > Computation::theTrixelizeOverlapTol
* Computation::triangleSemiPerimeter( p0
, p1
, p2
) )
1601 triangleQueue
->push_back( Computation::ZBufTriangle( this,
1611 Computation::PaintedPolygon3D::computeMean( ) const
1613 Concrete::Coords3D
res( 0, 0, 0 );
1614 typedef typeof points_ ListType
;
1615 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
1619 return ( 1. / points_
.size( ) ) * res
;
1622 const Computation::FacetLatticeVertex
*
1623 Computation::FacetLatticeEdge::getOther( const FacetLatticeEdge
* e
) const
1625 if( p0_
== e
->p0_
|| p0_
== e
->p1_
)
1633 Computation::FacetLatticeEdge::sharePoint( const FacetLatticeEdge
* e
) const
1644 Computation::FacetLatticeEdge::split( const Concrete::Length eyez
,
1645 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeEdge
* > > * edgeMem
,
1646 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeVertex
* > > * vertexMem
,
1647 const Computation::FacetLatticeEdge
** child1
, const Computation::FacetLatticeEdge
** child2
) const
1656 if( eyez
== Concrete::HUGE_LENGTH
)
1658 FacetLatticeVertex
* pNew
= new FacetLatticeVertex( 0.5 * ( p0_
->p3D_
+ p1_
->p3D_
), eyez
, vertexMem
->size( ) );
1659 vertexMem
->push_back( pNew
);
1660 child1_
= new Computation::FacetLatticeEdge( p0_
, pNew
);
1661 edgeMem
->push_back( child1_
);
1662 child2_
= new Computation::FacetLatticeEdge( pNew
, p1_
);
1663 edgeMem
->push_back( child2_
);
1667 // We compute the midpoint _in_view_, and then find where this is along the 3D line.
1668 Concrete::Coords2D mid2D
= 0.5 * ( p0_
->p2D_
+ p1_
->p2D_
);
1670 // If we write the point we seek in 3D as
1671 // p0_ + lambda * ( p1_ - p0_ )
1672 // then <lambda> must solve the overdetermined system
1675 const double ra
= ( p1_
->p3D_
.z_
- p0_
->p3D_
.z_
) / eyez
;
1676 Concrete::Coords2D
a( p1_
->p3D_
.x_
- p0_
->p3D_
.x_
+ mid2D
.x_
* ra
,
1677 p1_
->p3D_
.y_
- p0_
->p3D_
.y_
+ mid2D
.y_
* ra
);
1678 const double rb
= static_cast< double >( p0_
->p3D_
.z_
/ eyez
) - 1;
1679 Concrete::Coords2D
b( p0_
->p3D_
.x_
+ mid2D
.x_
* rb
,
1680 p0_
->p3D_
.y_
+ mid2D
.y_
* rb
);
1681 const double lambda
= - Concrete::innerScalar( a
, b
) / Concrete::innerScalar( a
, a
);
1683 FacetLatticeVertex
* pNew
= new FacetLatticeVertex( ( 1 - lambda
) * p0_
->p3D_
+ lambda
* p1_
->p3D_
, eyez
, vertexMem
->size( ) );
1684 vertexMem
->push_back( pNew
);
1685 child1_
= new Computation::FacetLatticeEdge( p0_
, pNew
);
1686 edgeMem
->push_back( child1_
);
1687 child2_
= new Computation::FacetLatticeEdge( pNew
, p1_
);
1688 edgeMem
->push_back( child2_
);
1696 Computation::FacetLatticeVertex::FacetLatticeVertex( const Concrete::Coords3D
& p3D
, const Concrete::Length eyez
, const size_t i
)
1697 : p3D_( p3D
), p2D_( p3D
.make2DAutomatic( eyez
) ), i_( i
)
1700 const Computation::FacetLatticeEdge
*
1701 Computation::FacetLatticeTriangle::getOther( const Computation::FacetLatticeEdge
*ea
, const Computation::FacetLatticeEdge
*eb
) const
1711 else if( ea
== e1_
)
1719 else if( ea
== e2_
)
1728 throw Exceptions::InternalError( "FacetTriangle::getOther called with alien edge." );
1732 Computation::FacetLatticeTriangle::fitsResolution( const Concrete::Length resolution
, const Concrete::Length eyez
,
1733 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeEdge
* > > * edgeMem
,
1734 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeVertex
* > > * vertexMem
,
1735 const Computation::FacetLatticeTriangle
** child1
, const Computation::FacetLatticeTriangle
** child2
) const
1737 const Computation::FacetLatticeEdge
* ec1
;
1738 const Computation::FacetLatticeEdge
* ec2
;
1740 Concrete::Length l0
= e0_
->length2D( );
1741 Concrete::Length l1
= e1_
->length2D( );
1742 Concrete::Length l2
= e2_
->length2D( );
1743 Concrete::Length lMax
= std::max( l0
, std::max( l1
, l2
) );
1745 if( lMax
< resolution
)
1750 const Computation::FacetLatticeEdge
* ea
= e0_
;
1751 const Computation::FacetLatticeEdge
* eb
= e1_
;
1752 const Computation::FacetLatticeEdge
* ec
= e2_
;
1759 else if( l2
== lMax
)
1767 ea
->split( eyez
, edgeMem
, vertexMem
, & ec1
, & ec2
);
1768 Computation::FacetLatticeEdge
* newEdge
= new Computation::FacetLatticeEdge( ea
->midpoint( ), eb
->getOther( ea
) );
1769 edgeMem
->push_back( newEdge
);
1770 if( eb
->sharePoint( ec2
) )
1772 *child1
= new Computation::FacetLatticeTriangle( ec2
, eb
, newEdge
);
1773 *child2
= new Computation::FacetLatticeTriangle( newEdge
, ec
, ec1
);
1777 *child1
= new Computation::FacetLatticeTriangle( ec1
, eb
, newEdge
);
1778 *child2
= new Computation::FacetLatticeTriangle( newEdge
, ec
, ec2
);
1785 RefCountPtr
< const Lang::Drawable2D
>
1786 Computation::FacetLatticeTriangle::paint( const RefCountPtr
< const Computation::FacetInterpolatorGray
> & interpolator
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
, const Concrete::Length eyez
) const
1788 Kernel::GraphicsState
* metaStatePtr
= new Kernel::GraphicsState( true );
1790 metaStatePtr
->nonStrokingColor_
= interpolator
->compute( Lang::THE_3D_IDENTITY
, lights
,
1791 Computation::triangleIncenter( v0_
->p3D_
, v1_
->p3D_
, v2_
->p3D_
),
1794 RefCountPtr
< const Kernel::GraphicsState
> metaState( metaStatePtr
);
1796 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
1798 // It's a pity we have to copy duplicate those points...
1799 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v0_
->p2D_
) ) );
1800 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v1_
->p2D_
) ) );
1801 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v2_
->p2D_
) ) );
1803 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::PaintedPolygon2D( metaState
, path
) );
1806 RefCountPtr
< const Lang::Drawable2D
>
1807 Computation::FacetLatticeTriangle::paint( const RefCountPtr
< const Computation::FacetInterpolatorRGB
> & interpolator
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
, const Concrete::Length eyez
) const
1809 Kernel::GraphicsState
* metaStatePtr
= new Kernel::GraphicsState( true );
1811 metaStatePtr
->nonStrokingColor_
= interpolator
->compute( Lang::THE_3D_IDENTITY
, lights
,
1812 Computation::triangleIncenter( v0_
->p3D_
, v1_
->p3D_
, v2_
->p3D_
),
1815 RefCountPtr
< const Kernel::GraphicsState
> metaState( metaStatePtr
);
1817 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
1819 // It's a pity we have to copy duplicate those points...
1820 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v0_
->p2D_
) ) );
1821 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v1_
->p2D_
) ) );
1822 path
->push_back( new Concrete::PathPoint2D( new Concrete::Coords2D( v2_
->p2D_
) ) );
1824 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::PaintedPolygon2D( metaState
, path
) );
1828 Computation::FacetLatticeTriangle::getVertexes( const Computation::FacetLatticeVertex
** va
, const Computation::FacetLatticeVertex
** vb
, const Computation::FacetLatticeVertex
** vc
) const
1835 // This function is very close to the PDF definition of a free-form triangle mesh.
1836 // 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.
1837 // 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.
1839 Computation::FacetLatticeTriangle::extendLattice( const Computation::FacetLatticeVertex
** va
, const Computation::FacetLatticeVertex
** vb
, const Computation::FacetLatticeVertex
** vc
) const
1841 // vc must be part of this triangle if we are to extend va--vb--vc.
1842 if( v0_
== *vc
|| v1_
== *vc
|| v2_
== *vc
)
1844 // First, we try to extend vb--vc (corresponding to flag=1)
1845 if( v0_
== *vb
|| v1_
== *vb
|| v2_
== *vb
)
1847 // We now update va and vb so that they define the edge that is extended.
1851 // Now we need to find which of our corners that is the added one.
1852 if( v0_
!= *va
&& v0_
!= *vb
)
1856 else if( v1_
!= *va
&& v1_
!= *vb
)
1867 // Then, we try to extend va--vc (corresponding to flag=2)
1868 if( v0_
== *va
|| v1_
== *va
|| v2_
== *va
)
1870 // We now update va and vb so that they define the edge that is extended.
1874 // Now we need to find which of our corners that is the added one.
1875 if( v0_
!= *va
&& v0_
!= *vb
)
1879 else if( v1_
!= *va
&& v1_
!= *vb
)
1895 Computation::FacetLatticeTriangle::display2D( std::ostream
& os
) const
1897 Concrete::Length lMax
= Concrete::ZERO_LENGTH
;
1899 Concrete::Length tmp
= v0_
->p2D_
.distanceTo( v1_
->p2D_
);
1906 Concrete::Length tmp
= v1_
->p2D_
.distanceTo( v2_
->p2D_
);
1913 Concrete::Length tmp
= v2_
->p2D_
.distanceTo( v0_
->p2D_
);
1920 os
<< "Triangle ( " << v0_
->p2D_
<< " -- " << v1_
->p2D_
<< " -- " << v2_
->p2D_
<< " ) "
1921 << " with 2D area " << Concrete::Area::offtype( Computation::triangleArea( v0_
->p2D_
, v1_
->p2D_
, v2_
->p2D_
) )
1922 << " and longest side " << Lang::Length( lMax
) ;
1926 Computation::FacetLatticeTriangle::display3D( std::ostream
& os
) const
1928 os
<< "Triangle ( " << v0_
->p3D_
<< " -- " << v1_
->p3D_
<< " -- " << v2_
->p3D_
<< " )" ;
1933 Computation::PaintedPolygon3D::makeLattice( PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeTriangle
* > > * lattice
,
1934 PtrOwner_back_Access
< std::list
< const Computation::FacetLatticeEdge
* > > * edgeMem
,
1935 PtrOwner_back_Access
< std::list
< const FacetLatticeVertex
* > > * vertexMem
,
1936 const Concrete::Length viewResolution
,
1937 const Concrete::Length eyez
, const Lang::Transform3D
& tf
) const
1939 if( points_
.size( ) < 3 )
1941 throw Exceptions::InternalError( "Less than three points in PaintedPolygon3D::makeLattice!" );
1944 std::list
< const Computation::FacetLatticeTriangle
* > jobQueue
;
1946 typedef typeof points_ ListType
;
1948 if( points_
.size( ) == 3 )
1950 ListType::const_iterator i
= points_
.begin( );
1951 Computation::FacetLatticeVertex
* p0
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1952 vertexMem
->push_back( p0
);
1954 Computation::FacetLatticeVertex
* p1
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1955 vertexMem
->push_back( p1
);
1957 Computation::FacetLatticeVertex
* p2
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1958 vertexMem
->push_back( p2
);
1960 Computation::FacetLatticeEdge
* e0
= new Computation::FacetLatticeEdge( p0
, p1
);
1961 edgeMem
->push_back( e0
);
1962 Computation::FacetLatticeEdge
* e1
= new Computation::FacetLatticeEdge( p1
, p2
);
1963 edgeMem
->push_back( e1
);
1964 Computation::FacetLatticeEdge
* e2
= new Computation::FacetLatticeEdge( p2
, p0
);
1965 edgeMem
->push_back( e2
);
1967 jobQueue
.push_back( new Computation::FacetLatticeTriangle( e0
, e1
, e2
) );
1971 ListType::const_iterator i
= points_
.begin( );
1972 Computation::FacetLatticeVertex
* p0
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1973 vertexMem
->push_back( p0
);
1975 Computation::FacetLatticeVertex
* p1
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1976 vertexMem
->push_back( p1
);
1979 Computation::FacetLatticeEdge
* e0
= new Computation::FacetLatticeEdge( p0
, p1
);
1980 edgeMem
->push_back( e0
);
1982 for( ; i
!= points_
.end( ); ++i
)
1984 Computation::FacetLatticeVertex
* p2
= new Computation::FacetLatticeVertex( i
->transformed( tf
), eyez
, vertexMem
->size( ) );
1985 vertexMem
->push_back( p2
);
1987 Computation::FacetLatticeEdge
* e1
= new Computation::FacetLatticeEdge( p1
, p2
);
1988 edgeMem
->push_back( e1
);
1990 Computation::FacetLatticeEdge
* e2
= new Computation::FacetLatticeEdge( p2
, p0
);
1991 edgeMem
->push_back( e2
);
1993 jobQueue
.push_back( new Computation::FacetLatticeTriangle( e0
, e1
, e2
) );
2000 while( ! jobQueue
.empty( ) )
2002 const Computation::FacetLatticeTriangle
* currentTriangle
= jobQueue
.front( );
2003 jobQueue
.pop_front( );
2004 const Computation::FacetLatticeTriangle
* child1
= 0;
2005 const Computation::FacetLatticeTriangle
* child2
= 0;
2006 if( currentTriangle
->fitsResolution( viewResolution
, eyez
, edgeMem
, vertexMem
, & child1
, & child2
) )
2008 lattice
->push_back( currentTriangle
);
2012 jobQueue
.push_back( child1
);
2013 jobQueue
.push_back( child2
);
2014 delete currentTriangle
;
2019 Computation::StrokedLine3D::StrokedLine3D( const Concrete::Coords3D
& p0
, const Concrete::Coords3D
& p1
, const RefCountPtr
< const Kernel::GraphicsState
> metaState
)
2020 : p0_( p0
), p1_( p1
), metaState_( metaState
)
2023 Computation::StrokedLine3D::~StrokedLine3D( )
2027 Computation::StrokedLine3D::push_zBufLine( const Lang::Transform3D
& tf
, const Concrete::Length eyez
, std::list
< const Computation::ZBufLine
* > * lineQueue
) const
2029 typedef Computation::ZBufLine::ZMap ZMapType
;
2030 typedef const Bezier::PolyCoeffs
< Concrete::Coords2D
> ViewType
;
2031 RefCountPtr
< ViewType
> nullView
= RefCountPtr
< ViewType
>( NullPtr
< ViewType
>( ) );
2032 if( tf
.isIdentity( ) )
2034 Concrete::Coords3D d
= p1_
- p0_
;
2035 RefCountPtr
< const ZMapType
> zMap( new ZMapType( p0_
, d
.directionNoFail( ), eyez
) );
2036 lineQueue
->push_back( new Computation::ZBufLine( this, zMap
, nullView
, p0_
.make2DAutomatic( eyez
), p1_
.make2DAutomatic( eyez
) ) );
2040 Concrete::Coords3D tfp0
= p0_
.transformed( tf
);
2041 Concrete::Coords3D tfp1
= p1_
.transformed( tf
);
2042 Concrete::Coords3D d
= tfp1
- tfp0
;
2043 RefCountPtr
< const ZMapType
> zMap( new ZMapType( tfp0
, d
.directionNoFail( ), eyez
) );
2044 lineQueue
->push_back( new Computation::ZBufLine( this, zMap
, nullView
, tfp0
.make2DAutomatic( eyez
), tfp1
.make2DAutomatic( eyez
) ) );
2049 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
)
2050 : Computation::StrokedLine3D( p0
, p1
, metaState
),
2051 p0front_( p0front
),
2055 Computation::StrokedSplineSegment3D::~StrokedSplineSegment3D( )
2059 Computation::StrokedSplineSegment3D::push_zBufLine( const Lang::Transform3D
& tf
, const Concrete::Length eyez
, std::list
< const Computation::ZBufLine
* > * lineQueue
) const
2061 typedef Computation::ZBufLine::ZMap ZMapType
;
2062 typedef const Bezier::PolyCoeffs
< Concrete::Coords2D
> ViewType
;
2063 if( tf
.isIdentity( ) )
2065 Concrete::Coords3D d
= p1_
- p0_
;
2066 RefCountPtr
< const ZMapType
> zMap( new ZMapType( p0_
, d
.directionNoFail( ), eyez
) );
2067 RefCountPtr
< ViewType
> bezierView
= RefCountPtr
< ViewType
>( new ViewType( Bezier::ControlPoints
< Concrete::Coords2D
>( p0_
.make2DAutomatic( eyez
), p0front_
.make2DAutomatic( eyez
), p1rear_
.make2DAutomatic( eyez
), p1_
.make2DAutomatic( eyez
) ) ) );
2068 lineQueue
->push_back( new Computation::ZBufLine( this, zMap
, bezierView
, p0_
.make2DAutomatic( eyez
), p1_
.make2DAutomatic( eyez
) ) );
2072 Concrete::Coords3D tfp0
= p0_
.transformed( tf
);
2073 Concrete::Coords3D tfp0front
= p0front_
.transformed( tf
);
2074 Concrete::Coords3D tfp1rear
= p1rear_
.transformed( tf
);
2075 Concrete::Coords3D tfp1
= p1_
.transformed( tf
);
2076 Concrete::Coords3D d
= tfp1
- tfp0
;
2077 RefCountPtr
< const ZMapType
> zMap( new ZMapType( tfp0
, d
.directionNoFail( ), eyez
) );
2078 RefCountPtr
< ViewType
> bezierView
= RefCountPtr
< ViewType
>( new ViewType( Bezier::ControlPoints
< Concrete::Coords2D
>( tfp0
.make2DAutomatic( eyez
), tfp0front
.make2DAutomatic( eyez
), tfp1rear
.make2DAutomatic( eyez
), tfp1
.make2DAutomatic( eyez
) ) ) );
2079 lineQueue
->push_back( new Computation::ZBufLine( this, zMap
, bezierView
, tfp0
.make2DAutomatic( eyez
), tfp1
.make2DAutomatic( eyez
) ) );
2084 Computation::FilledPolygon3D::FilledPolygon3D( const RefCountPtr
< const Kernel::GraphicsState
> & metaState
,
2085 const Concrete::UnitFloatTriple
& normal
, Concrete::Length m
,
2086 Concrete::Length tiebreaker
)
2087 : Computation::PaintedPolygon3D( false, normal
, m
, tiebreaker
), metaState_( metaState
) // false means not single-sided.
2090 Computation::FilledPolygon3D::~FilledPolygon3D( )
2093 RefCountPtr
< const Lang::PaintedPolygon2D
>
2094 Computation::FilledPolygon3D::polygon_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
) const
2096 // A FilledPolygon3D is characterized by that it doesn't take notice about the lights or orientation.
2098 Concrete::Length eyez
= dyn
->getEyeZ( );
2100 RefCountPtr
< Lang::ElementaryPath2D
> path
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D( ) );
2102 if( tf
.isIdentity( ) )
2104 typedef typeof points_ ListType
;
2105 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
2107 path
->push_back( new Concrete::PathPoint2D( i
->make2D( eyez
) ) );
2112 typedef typeof points_ ListType
;
2113 for( ListType::const_iterator i
= points_
.begin( ); i
!= points_
.end( ); ++i
)
2115 path
->push_back( new Concrete::PathPoint2D( i
->transformed( tf
).make2D( eyez
) ) );
2119 return RefCountPtr
< const Lang::PaintedPolygon2D
>( new Lang::PaintedPolygon2D( metaState_
, path
) );
2122 RefCountPtr
< const Lang::Color
>
2123 Computation::FilledPolygon3D::getColor( ) const
2125 return metaState_
->nonStrokingColor_
;
2129 Computation::FilledPolygon3D::gcMark( Kernel::GCMarkedSet
& marked
)
2131 // const_cast< Kernel::GraphicsState * >( metaState_.getPtr( ) )->gcMark( marked );
2134 Computation::NullPolygon3D::NullPolygon3D( )
2135 : Computation::PaintedPolygon3D( true, Concrete::UnitFloatTriple( 1., 0., 0., 1. ), 0, Concrete::ZERO_LENGTH
)
2138 Computation::NullPolygon3D::~NullPolygon3D( )
2141 RefCountPtr
< const Lang::PaintedPolygon2D
>
2142 Computation::NullPolygon3D::polygon_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const std::list
< RefCountPtr
< const Lang::LightSource
> > & lights
) const
2144 throw Exceptions::InternalError( "NullPolygon3D::polygon_to2D was invoked!" );
2145 // return Lang::THE_NULL_POLYGON2D;
2148 RefCountPtr
< const Lang::Color
>
2149 Computation::NullPolygon3D::getColor( ) const
2151 return Lang::THE_BLACK
;
2155 Computation::NullPolygon3D::gcMark( Kernel::GCMarkedSet
& marked
)
2159 Lang::PaintedPolygon2D::PaintedPolygon2D( RefCountPtr
< const Kernel::GraphicsState
> metaState
, RefCountPtr
< const Lang::ElementaryPath2D
> path
)
2160 : Lang::PaintedPath2D( metaState
, "E" ) // "E" for "extended fill"
2162 if( ! path
->isClosed( ) )
2164 throw Exceptions::InternalError( "Attempt to create PaintedPolygon2D with non-closed path." );
2169 Lang::PaintedPolygon2D::~PaintedPolygon2D( )
2172 RefCountPtr
< const Lang::Drawable2D
>
2173 Lang::PaintedPolygon2D::clip( std::list
< Computation::ZBufTriangle
> * regions
, const RefCountPtr
< const Lang::PaintedPolygon2D
> selfRef
) const
2175 if( regions
->empty( ) )
2177 throw Exceptions::InternalError( "Empty list of regions in PaintedPolygon2D::clip. (This triangle should not have been generated at all!)" );
2179 if( regions
->size( ) == 1 )
2181 const Computation::ZBufTriangle
& theClip
= regions
->front( );
2182 const Lang::ElementaryPath2D
& paintPath
= * path_
.front( );
2183 bool isInside
= true;
2184 for( Lang::ElementaryPath2D::const_iterator i
= paintPath
.begin( ); i
!= paintPath
.end( ); ++i
)
2186 if( ! theClip
.contains( *((*i
)->mid_
), Computation::theTrixelizeOverlapTol
) )
2198 // If we reach here, clipping shall be done
2199 Lang::Clipped2D
* resPtr
= new Lang::Clipped2D( selfRef
, "W" );
2200 Lang::ZBuf::trianglesToPolys( regions
, resPtr
);
2201 RefCountPtr
< const Lang::Clipped2D
> res( resPtr
);
2203 if( selfRef
->isContainedIn( resPtr
) )
2208 const bool SHOW_POLYS
= false;
2211 return res
->debugPolys( );
2219 Lang::PaintedPath2D::isContainedIn( const Lang::Clipped2D
* clipping
) const
2221 if( ! clipping
->isSingleConvexPoly( Computation::theTrixelizeOverlapTol
) )
2226 typedef typeof path_ PathType
;
2227 for( PathType::const_iterator subpath
= path_
.begin( ); subpath
!= path_
.end( ); ++subpath
)
2229 typedef typeof **subpath SubpathType
;
2230 for( SubpathType::const_iterator i
= (*subpath
)->begin( ); i
!= (*subpath
)->end( ); ++i
)
2232 Concrete::PathPoint2D
* pathPoint
= *i
;
2233 if( pathPoint
->rear_
!= pathPoint
->mid_
||
2234 pathPoint
->front_
!= pathPoint
->mid_
)
2238 if( ! clipping
->convexPolyContains( *(pathPoint
->mid_
), Computation::theTrixelizeOverlapTol
) )
2249 Lang::PaintedPath3D::PaintedPath3D( RefCountPtr
< const Kernel::GraphicsState
> metaState
,
2250 const char * paintCmd
, Concrete::Length tiebreaker
)
2251 : metaState_( metaState
), paintCmd_( paintCmd
), tiebreaker_( tiebreaker
)
2254 Lang::PaintedPath3D::PaintedPath3D( RefCountPtr
< const Kernel::GraphicsState
> metaState
,
2255 RefCountPtr
< const Lang::ElementaryPath3D
> path
,
2256 const char * paintCmd
, Concrete::Length tiebreaker
)
2257 : metaState_( metaState
), paintCmd_( paintCmd
), tiebreaker_( tiebreaker
)
2262 Lang::PaintedPath3D::PaintedPath3D( RefCountPtr
< const Kernel::GraphicsState
> metaState
,
2263 RefCountPtr
< const Lang::MultiPath3D
> paths
,
2264 const char * paintCmd
, Concrete::Length tiebreaker
)
2265 : metaState_( metaState
), paintCmd_( paintCmd
), tiebreaker_( tiebreaker
)
2267 for( Lang::MultiPath3D::const_iterator i
= paths
->begin( ); i
!= paths
->end( ); ++i
)
2270 typedef const Lang::ElementaryPath3D ArgType
;
2271 RefCountPtr
< ArgType
> subpath
= (*i
).down_cast
< ArgType
>( );
2272 if( subpath
!= NullPtr
< ArgType
>( ) )
2274 addSubPath( subpath
);
2280 typedef const Lang::CompositePath3D ArgType
;
2281 ArgType
* subpath
= dynamic_cast< ArgType
* >( (*i
).getPtr( ) );
2284 addSubPath( subpath
->getElementaryPath( ) );
2288 throw Exceptions::InternalError( "Painting 3D path: Encountered a subpath of unexpected type" );
2292 Lang::PaintedPath3D::~PaintedPath3D( )
2295 RefCountPtr
< const Lang::Class
> Lang::PaintedPath3D::TypeID( new Lang::SystemFinalClass( strrefdup( "PaintedPath3D" ) ) );
2296 TYPEINFOIMPL( PaintedPath3D
);
2299 Lang::PaintedPath3D::addSubPath( RefCountPtr
< const Lang::ElementaryPath3D
> subpath
)
2301 path_
.push_back( subpath
);
2304 RefCountPtr
< const Lang::Drawable2D
>
2305 Lang::PaintedPath3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2307 Concrete::Length eyez
= dyn
->getEyeZ( );
2309 RefCountPtr
< const Lang::Group2D
> res( Lang::THE_NULL2D
);
2311 if( tf
.isIdentity( ) )
2313 if( ! metaState_
->dash_
->isSolid( ) && *paintCmd_
== 'S' )
2315 for( std::list
< RefCountPtr
< const Lang::ElementaryPath3D
> >::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
2317 (*i
)->dashifyIn2D( & res
, eyez
, metaState_
);
2322 for( std::list
< RefCountPtr
< const Lang::ElementaryPath3D
> >::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
2324 res
= RefCountPtr
< const Lang::Group2D
>( new Lang::GroupPair2D( RefCountPtr
< const Lang::Drawable2D
>( new Lang::PaintedPath2D( metaState_
, (*i
)->make2D( eyez
), paintCmd_
) ),
2332 if( ! metaState_
->dash_
->isSolid( ) && *paintCmd_
== 'S' )
2334 for( std::list
< RefCountPtr
< const Lang::ElementaryPath3D
> >::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
2336 (*i
)->elementaryTransformed( tf
)->dashifyIn2D( & res
, eyez
, metaState_
);
2341 for( std::list
< RefCountPtr
< const Lang::ElementaryPath3D
> >::const_iterator i
= path_
.begin( ); i
!= path_
.end( ); ++i
)
2343 res
= RefCountPtr
< const Lang::Group2D
>( new Lang::GroupPair2D( RefCountPtr
< const Lang::Drawable2D
>( new Lang::PaintedPath2D( metaState_
,
2344 (*i
)->elementaryTransformed( tf
)->make2D( eyez
),
2355 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
2357 if( strcmp( paintCmd_
, "S" ) == 0 )
2359 typedef typeof path_ ListType
;
2360 for( ListType::const_iterator subi
= path_
.begin( ); subi
!= path_
.end( ); ++subi
)
2362 const RefCountPtr
< const Lang::ElementaryPath3D
> & theSub
= *subi
;
2364 if( theSub
->size( ) < 2 )
2369 typedef typeof *theSub SubListType
;
2370 SubListType::const_iterator i
= theSub
->begin( );
2371 Concrete::Coords3D p0
= (*i
)->mid_
->transformed( tf
);
2372 SubListType::const_iterator iLast
= i
;
2374 for( ; i
!= theSub
->end( ); iLast
= i
, ++i
)
2376 Concrete::Coords3D p1
= (*i
)->mid_
->transformed( tf
);
2377 if( (*iLast
)->front_
!= (*iLast
)->mid_
|| (*i
)->rear_
!= (*i
)->mid_
)
2379 linePile
->push_back( RefCountPtr
< Computation::StrokedSplineSegment3D
>
2380 ( new Computation::StrokedSplineSegment3D( p0
, (*iLast
)->front_
->transformed( tf
), (*i
)->rear_
->transformed( tf
), p1
, metaState_
) ) );
2384 linePile
->push_back( RefCountPtr
< Computation::StrokedLine3D
>
2385 ( new Computation::StrokedLine3D( p0
, p1
, metaState_
) ) );
2389 if( theSub
->isClosed( ) )
2391 i
= theSub
->begin( );
2392 Concrete::Coords3D p1
= (*i
)->mid_
->transformed( tf
);
2393 if( (*iLast
)->front_
!= (*iLast
)->mid_
|| (*i
)->rear_
!= (*i
)->mid_
)
2395 linePile
->push_back( RefCountPtr
< Computation::StrokedSplineSegment3D
>
2396 ( new Computation::StrokedSplineSegment3D( p0
, (*iLast
)->front_
->transformed( tf
), (*i
)->rear_
->transformed( tf
), p1
, metaState_
) ) );
2400 linePile
->push_back( RefCountPtr
< Computation::StrokedLine3D
>
2401 ( new Computation::StrokedLine3D( p0
, p1
, metaState_
) ) );
2409 if( ! ( strcmp( paintCmd_
, "f" ) == 0 ||
2410 strcmp( paintCmd_
, "B" ) == 0 ) )
2412 throw Exceptions::MiscellaneousRequirement( "Only stroked and (non-*) filled polygons can be put i a z buffer." );
2416 // When we get here we know that the paintCmd_ is "f" or "B", that is, a plain fill.
2418 // if( path.size( ) > 1 )
2420 // WARN_OR_THROW( Exceptionssha::MiscellanueousRequirement( "The result from triangularizing a composite path may not be what is expected." ) );
2423 typedef typeof path_ ListType
;
2424 for( ListType::const_iterator subi
= path_
.begin( ); subi
!= path_
.end( ); ++subi
)
2426 const RefCountPtr
< const Lang::ElementaryPath3D
> & theSub
= *subi
;
2428 if( theSub
->size( ) < 3 )
2432 if( ! theSub
->isClosed( ) )
2437 typedef typeof *theSub SubListType
;
2439 RefCountPtr
< Computation::FilledPolygon3D
> newPoly
= RefCountPtr
< Computation::FilledPolygon3D
>( NullPtr
< Computation::FilledPolygon3D
>( ) );
2441 // First we must compute an equation for the polygon!
2443 Concrete::Coords3D
p0( 0, 0, 0 );
2444 Concrete::Coords3D
p1( 0, 0, 0 );
2445 Concrete::Coords3D
p2( 0, 0, 0 );
2446 theSub
->getRepresentativePoints( tf
, & p0
, & p1
, & p2
);
2450 Concrete::UnitFloatTriple normal
= Concrete::crossDirection( p2
- p0
, p1
- p0
);
2451 Concrete::Length m
= Concrete::inner( normal
, p0
);
2452 newPoly
= RefCountPtr
< Computation::FilledPolygon3D
>( new Computation::FilledPolygon3D( metaState_
, normal
, m
, tiebreaker_
) );
2454 catch( const NonLocalExit::CrossDirectionOfParallel
& ball
)
2456 // This means that the crossDirection called failed because the vectors were parallel.
2457 // A polygon of lower dimension is invisible, so we may just continue
2462 zBufPile
->push_back( newPoly
);
2464 for( SubListType::const_iterator i
= theSub
->begin( ); i
!= theSub
->end( ); ++i
)
2466 if( (*i
)->front_
!= (*i
)->mid_
|| (*i
)->rear_
!= (*i
)->mid_
)
2468 throw "Corner has handle";
2470 newPoly
->pushPoint( (*i
)->mid_
->transformed( tf
) );
2476 Lang::PaintedPath3D::gcMark( Kernel::GCMarkedSet
& marked
)
2480 Lang::SingleSided3DGray::SingleSided3DGray( const RefCountPtr
< const Lang::ElementaryPath3D
> & points
,
2481 const RefCountPtr
< const Computation::FacetInterpolatorGray
> & interpolator
,
2483 const Concrete::UnitFloatTriple
& polygonUnitNormal
,
2485 Concrete::Length tiebreaker
,
2486 Concrete::Length viewResolution
,
2487 Computation::FacetShadeOrder shadeOrder
)
2488 : points_( points
), interpolator_( interpolator
), singleSided_( singleSided
), polygonUnitNormal_( polygonUnitNormal
), m_( m
), tiebreaker_( tiebreaker
),
2489 viewResolution_( viewResolution
), shadeOrder_( shadeOrder
)
2492 Lang::SingleSided3DGray::~SingleSided3DGray( )
2495 RefCountPtr
< const Lang::Class
> Lang::SingleSided3DGray::TypeID( new Lang::SystemFinalClass( strrefdup( "SingleSided3D(gray)" ) ) );
2496 TYPEINFOIMPL( SingleSided3DGray
);
2498 RefCountPtr
< const Lang::Drawable2D
>
2499 Lang::SingleSided3DGray::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2501 throw Exceptions::NotImplemented( "SingleSided3DGray::typed_to2D; What light scene should be used?" );
2505 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
2507 Concrete::UnitFloatTriple Tnormal
= tf
.transformPlaneUnitNormal( polygonUnitNormal_
);
2509 double ax
= fabs( polygonUnitNormal_
.x_
);
2510 double ay
= fabs( polygonUnitNormal_
.y_
);
2511 double az
= fabs( polygonUnitNormal_
.z_
);
2512 Concrete::Coords3D
x0( 0, 0, 0 );
2513 if( ax
>= ay
&& ax
>= az
)
2515 x0
= Concrete::Coords3D( m_
/ polygonUnitNormal_
.x_
, 0, 0 );
2519 x0
= Concrete::Coords3D( 0, m_
/ polygonUnitNormal_
.y_
, 0 );
2523 x0
= Concrete::Coords3D( 0, 0, m_
/ polygonUnitNormal_
.z_
);
2525 Concrete::Length Tm
= Concrete::inner( Tnormal
, x0
.transformed( tf
) );
2527 RefCountPtr
< Computation::SingleSidedPolygon3DGray
> res
=
2528 RefCountPtr
< Computation::SingleSidedPolygon3DGray
>
2529 ( new Computation::SingleSidedPolygon3DGray( interpolator_
->transformed( tf
),
2537 typedef Lang::ElementaryPath3D ListType
;
2538 for( ListType::const_iterator i
= points_
->begin( ); i
!= points_
->end( ); ++i
)
2540 // The creator of *this is responsible for asserting that there are no handles at the pathpoints.
2541 res
->pushPoint( (*i
)->mid_
->transformed( tf
) );
2545 zBufPile
->push_back( res
);
2549 Lang::SingleSided3DGray::gcMark( Kernel::GCMarkedSet
& marked
)
2551 const_cast< Lang::ElementaryPath3D
* >( points_
.getPtr( ) )->gcMark( marked
);
2552 const_cast< Computation::FacetInterpolatorGray
* >( interpolator_
.getPtr( ) )->gcMark( marked
);
2556 Lang::SingleSided3DRGB::SingleSided3DRGB( const RefCountPtr
< const Lang::ElementaryPath3D
> & points
,
2557 const RefCountPtr
< const Computation::FacetInterpolatorRGB
> & interpolator
,
2559 const Concrete::UnitFloatTriple
& polygonUnitNormal
,
2561 Concrete::Length tiebreaker
,
2562 Concrete::Length viewResolution
,
2563 Computation::FacetShadeOrder shadeOrder
)
2564 : points_( points
), interpolator_( interpolator
), singleSided_( singleSided
), polygonUnitNormal_( polygonUnitNormal
), m_( m
), tiebreaker_( tiebreaker
),
2565 viewResolution_( viewResolution
), shadeOrder_( shadeOrder
)
2568 Lang::SingleSided3DRGB::~SingleSided3DRGB( )
2571 RefCountPtr
< const Lang::Class
> Lang::SingleSided3DRGB::TypeID( new Lang::SystemFinalClass( strrefdup( "SingleSided3D(RGB)" ) ) );
2572 TYPEINFOIMPL( SingleSided3DRGB
);
2574 RefCountPtr
< const Lang::Drawable2D
>
2575 Lang::SingleSided3DRGB::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2577 throw Exceptions::NotImplemented( "SingleSided3DRGB::typed_to2D; What light scene should be used?" );
2581 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
2583 Concrete::UnitFloatTriple Tnormal
= tf
.transformPlaneUnitNormal( polygonUnitNormal_
);
2585 double ax
= fabs( polygonUnitNormal_
.x_
);
2586 double ay
= fabs( polygonUnitNormal_
.y_
);
2587 double az
= fabs( polygonUnitNormal_
.z_
);
2588 Concrete::Coords3D
x0( 0, 0, 0 );
2589 if( ax
>= ay
&& ax
>= az
)
2591 x0
= Concrete::Coords3D( m_
/ polygonUnitNormal_
.x_
, 0, 0 );
2595 x0
= Concrete::Coords3D( 0, m_
/ polygonUnitNormal_
.y_
, 0 );
2599 x0
= Concrete::Coords3D( 0, 0, m_
/ polygonUnitNormal_
.z_
);
2601 Concrete::Length Tm
= Concrete::inner( Tnormal
, x0
.transformed( tf
) );
2603 RefCountPtr
< Computation::SingleSidedPolygon3DRGB
> res
=
2604 RefCountPtr
< Computation::SingleSidedPolygon3DRGB
>
2605 ( new Computation::SingleSidedPolygon3DRGB( interpolator_
->transformed( tf
),
2613 typedef Lang::ElementaryPath3D ListType
;
2614 for( ListType::const_iterator i
= points_
->begin( ); i
!= points_
->end( ); ++i
)
2616 // The creator of *this is responsible for asserting that there are no handles at the pathpoints.
2617 res
->pushPoint( (*i
)->mid_
->transformed( tf
) );
2621 zBufPile
->push_back( res
);
2625 Lang::SingleSided3DRGB::gcMark( Kernel::GCMarkedSet
& marked
)
2627 const_cast< Lang::ElementaryPath3D
* >( points_
.getPtr( ) )->gcMark( marked
);
2628 const_cast< Computation::FacetInterpolatorRGB
* >( interpolator_
.getPtr( ) )->gcMark( marked
);
2633 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
)
2634 : metaState_( metaState
), pile_( pile
), linePile_( linePile
), lightPile_( lightPile
)
2637 Lang::ZBuf::~ZBuf( )
2641 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
2644 typedef typeof *pile_ ListType
;
2645 for( ListType::const_iterator i
= pile_
->begin( ); i
!= pile_
->end( ); ++i
)
2647 zBufPile
->push_back( *i
);
2651 typedef typeof *linePile_ ListType
;
2652 for( ListType::const_iterator i
= linePile_
->begin( ); i
!= linePile_
->end( ); ++i
)
2654 linePile
->push_back( *i
);
2660 Lang::ZBuf::gcMark( Kernel::GCMarkedSet
& marked
)
2662 // At the time of writing, PaintedPolygon3D is not involved in gc.
2666 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
)
2667 : metaState_( metaState
), pile_( pile
), linePile_( linePile
), lightPile_( lightPile
)
2670 Lang::ZSorter::~ZSorter( )
2674 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
2677 typedef typeof *pile_ ListType
;
2678 for( ListType::const_iterator i
= pile_
->begin( ); i
!= pile_
->end( ); ++i
)
2680 zBufPile
->push_back( *i
);
2684 typedef typeof *linePile_ ListType
;
2685 for( ListType::const_iterator i
= linePile_
->begin( ); i
!= linePile_
->end( ); ++i
)
2687 linePile
->push_back( *i
);
2693 Lang::ZSorter::gcMark( Kernel::GCMarkedSet
& marked
)
2695 // At the time of writing, PaintedPolygon3D is not involved in gc.
2699 Lang::Transformed3D::Transformed3D( RefCountPtr
< const Lang::Drawable3D
> element
, const Lang::Transform3D
& mytf
)
2700 : mytf_( mytf
), element_( element
)
2703 Lang::Transformed3D::~Transformed3D( )
2706 RefCountPtr
< const Lang::Drawable2D
>
2707 Lang::Transformed3D::typed_to2D( const Kernel::PassedDyn
& dyn
, const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Drawable3D
> & self
) const
2709 return element_
->typed_to2D( dyn
, Lang::Transform3D( tf
, mytf_
), element_
);
2713 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
2715 element_
->polygonize( zBufPile
, linePile
, dyn
, Lang::Transform3D( tf
, mytf_
), element_
);
2719 Lang::Transformed3D::findTags( std::vector
< Kernel::ValueRef
> * dst
, const Kernel::PassedDyn
& dyn
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
2721 element_
->findTags( dst
, dyn
, key
, Lang::Transform3D( tf
, mytf_
) );
2725 Lang::Transformed3D::findOneTag( Kernel::EvalState
* evalState
, Lang::Symbol::KeyType key
, const Lang::Transform3D
& tf
) const
2728 element_
->findOneTag( evalState
, key
, Lang::Transform3D( tf
, mytf_
) );
2732 Lang::Transformed3D::gcMark( Kernel::GCMarkedSet
& marked
)
2734 const_cast< Lang::Drawable3D
* >( element_
.getPtr( ) )->gcMark( marked
);
2737 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
)
2738 : textState_( textState
), elements_( elements
), mybbox_( mybbox
)
2741 Lang::Text::~Text( )
2745 Lang::Text::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
2747 if( textState_
->font_
->outline( ) )
2749 if( ( pdfState
->text_
.knockout_
& Kernel::TextState::KNOCKOUT_UNDEFINED_BIT
) != 0 &&
2750 ( pdfState
->text_
.knockout_
& Kernel::TextState::KNOCKOUT_FLAG_BIT
) == 0 )
2752 Kernel::TextState newState
;
2753 newState
.knockout_
= 0; /* Clear the KNOCKOUT_FLAG_BIT. */
2754 Helpers::newTransparencyGroup( RefCountPtr
< const Lang::Drawable2D
>
2755 ( new Lang::Text( RefCountPtr
< const Kernel::TextState
>( new Kernel::TextState( newState
, *textState_
) ),
2758 false, /* The group shall be isolated. */
2759 false, /* Not knockout. */
2760 Lang::THE_INHERITED_COLOR_SPACE
)->shipout( os
, pdfState
, tf
);
2764 Lang::Transform2D
textMatrix( 0, 0, 0, 0, Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
);
2765 Lang::Transform2D
lineMatrix( 0, 0, 0, 0, Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
);
2766 lineMatrix
.replaceBy( Lang::THE_2D_IDENTITY
);
2767 textMatrix
.replaceBy( lineMatrix
);
2768 typedef typeof *elements_ ListType
;
2769 for( ListType::const_iterator i
= elements_
->begin( ); i
!= elements_
->end( ); ++i
)
2771 (*i
)->shipout_outlined( os
, pdfState
, tf
, & textMatrix
, & lineMatrix
, 0 ); /* 0 means that this is a painting operation, not clipping. */
2777 pdfState
->resources_
->requireProcedureSet( SimplePDF::PDF_Resources::PROC_SET_TEXT
);
2779 os
<< "BT" << std::endl
;
2780 if( ! tf
.isIdentity( ) )
2783 os
<< " Tm" << std::endl
;
2786 pdfState
->text_
.synchKnockout( os
, textState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
2788 typedef typeof *elements_ ListType
;
2789 for( ListType::const_iterator i
= elements_
->begin( ); i
!= elements_
->end( ); ++i
)
2791 (*i
)->shipout( os
, pdfState
, tf
);
2793 os
<< "ET" << std::endl
;
2798 Lang::Text::shipout_clip( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
, const RefCountPtr
< const Lang::Drawable2D
> & content
) const
2800 if( textState_
->font_
->outline( ) )
2802 Lang::Transform2D
textMatrix( 0, 0, 0, 0, Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
);
2803 Lang::Transform2D
lineMatrix( 0, 0, 0, 0, Concrete::ZERO_LENGTH
, Concrete::ZERO_LENGTH
);
2804 textMatrix
.replaceBy( Lang::THE_2D_IDENTITY
);
2805 lineMatrix
.replaceBy( Lang::THE_2D_IDENTITY
);
2806 if( ( pdfState
->text_
.knockout_
& Kernel::TextState::KNOCKOUT_UNDEFINED_BIT
) != 0 &&
2807 ( pdfState
->text_
.knockout_
& Kernel::TextState::KNOCKOUT_FLAG_BIT
) == 0 )
2809 /* If the text knockout mode is false (by default, it is true), we emulate the effect by creating a temporary
2810 * object with default knockout mode inside a transparency group with the correct knockout mode, and then
2811 * shipout that object instead.
2813 Kernel::TextState newState
;
2814 newState
.knockout_
= 0; /* Clear the KNOCKOUT_FLAG_BIT. */
2815 Helpers::newTransparencyGroup( RefCountPtr
< const Lang::Drawable2D
>
2816 ( new Lang::TextMasked2D( content
,
2817 RefCountPtr
< const Lang::Text
>
2818 ( new Lang::Text( RefCountPtr
< const Kernel::TextState
>( new Kernel::TextState( newState
, *textState_
) ),
2821 false, /* The group shall be isolated. */
2822 false, /* Not knockout. */
2823 Lang::THE_INHERITED_COLOR_SPACE
)->shipout( os
, pdfState
, tf
);
2827 RefCountPtr
< const Lang::ElementaryPath2D
> theBBox
= content
->bbox( Lang::Drawable2D::BOUNDING
)->elementaryTransformed( tf
);
2828 Concrete::Coords2D
llcorner( 0, 0 );
2829 Concrete::Coords2D
urcorner( 0, 0 );
2830 if( ! theBBox
->boundingRectangle( & llcorner
, & urcorner
) )
2832 throw Exceptions::InternalError( "Text mask: The content has no bounding box!" );
2835 RefCountPtr
< SimplePDF::PDF_Stream_out
> form
;
2836 RefCountPtr
< SimplePDF::PDF_Object
> indirection
= SimplePDF::indirect( form
, & Kernel::theIndirectObjectCount
);
2838 RefCountPtr
< SimplePDF::PDF_Resources
> resources
;
2839 (*form
)[ "Resources" ] = SimplePDF::indirect( resources
, & Kernel::theIndirectObjectCount
);
2841 (*form
)[ "Subtype" ] = SimplePDF::newName( "Form" );
2842 (*form
)[ "FormType" ] = SimplePDF::newInt( 1 );
2843 (*form
)[ "BBox" ] = RefCountPtr
< SimplePDF::PDF_Vector
>( new SimplePDF::PDF_Vector( llcorner
.x_
.offtype
< 1, 0 >( ), llcorner
.y_
.offtype
< 1, 0 >( ),
2844 urcorner
.x_
.offtype
< 1, 0 >( ), urcorner
.y_
.offtype
< 1, 0 >( ) ) );
2846 Kernel::PageContentStates
contentState( resources
);
2847 content
->shipout( form
->data
, & contentState
, tf
);
2849 const SimplePDF::PDF_Name
& xoName
= pdfState
->resources_
->nameofXObject( indirection
);
2850 typedef typeof *elements_ ListType
;
2851 for( ListType::const_iterator i
= elements_
->begin( ); i
!= elements_
->end( ); ++i
)
2853 (*i
)->shipout_outlined( os
, pdfState
, tf
, & textMatrix
, & lineMatrix
, & xoName
); /* Passing xoName means "clip". */
2859 Kernel::Auto_qQ
auto_qQ( & pdfState
->graphics_
, & pdfState
->text_
, os
);
2860 if( ! tf
.isIdentity( ) )
2863 os
<< " cm" << std::endl
;
2866 pdfState
->resources_
->requireProcedureSet( SimplePDF::PDF_Resources::PROC_SET_TEXT
);
2868 os
<< "BT" << std::endl
;
2870 pdfState
->text_
.synchKnockout( os
, textState_
.getPtr( ), pdfState
->resources_
.getPtr( ) );
2872 typedef typeof *elements_ ListType
;
2873 for( ListType::const_iterator i
= elements_
->begin( ); i
!= elements_
->end( ); ++i
)
2875 (*i
)->shipout( os
, pdfState
, THE_2D_IDENTITY
, true ); /* true means "clip" */
2877 os
<< "ET" << std::endl
;
2879 content
->shipout( os
, pdfState
, THE_2D_IDENTITY
);
2883 RefCountPtr
< const Lang::ElementaryPath2D
>
2884 Lang::Text::bbox( Lang::Drawable2D::BoxType boxType
) const
2890 Lang::Text::gcMark( Kernel::GCMarkedSet
& marked
)
2892 typedef typeof *elements_ ListType
;
2893 for( ListType::const_iterator i
= elements_
->begin( ); i
!= elements_
->end( ); ++i
)
2895 const_cast< Lang::TextOperation
* >( i
->getPtr( ) )->gcMark( marked
);
2902 RefCountPtr
< const Lang::TransparencyGroup
>
2903 Helpers::newSolidTransparencyGroup( const RefCountPtr
< const Lang::Drawable2D
> & obj2
, const RefCountPtr
< const Lang::Drawable2D
> & obj1
)
2905 return Helpers::newTransparencyGroup( Helpers::newGroup2D( Kernel::THE_DEFAULT_STATE
, obj2
, obj1
),
2908 Lang::THE_INHERITED_COLOR_SPACE
);
2911 RefCountPtr
< const Lang::TransparencyGroup
>
2912 Helpers::newSolidTransparencyGroup( const RefCountPtr
< const Lang::Drawable2D
> & obj3
, const RefCountPtr
< const Lang::Drawable2D
> & obj2
, const RefCountPtr
< const Lang::Drawable2D
> & obj1
)
2914 return Helpers::newTransparencyGroup( Helpers::newGroup2D( Kernel::THE_DEFAULT_STATE
, obj3
, obj2
, obj1
),
2917 Lang::THE_INHERITED_COLOR_SPACE
);
2922 Computation::operator < ( const Computation::UndirectedEdge
& p1
, const Computation::UndirectedEdge
& p2
)
2924 if( p1
.low( ) < p2
.low( ) )
2928 if( p1
.low( ) > p2
.low( ) )
2932 return p1
.high( ) < p2
.high( );