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