Mutators for Group and Group3D states.
[shapes.git] / source / coredraw.cc
blob140cb735bcb09f279729cb70c0bef569674f52aa
1 #include <cmath>
3 #include "Shapes_Helpers_decls.h"
5 #include "shapescore.h"
6 #include "globals.h"
7 #include "shapesexceptions.h"
8 #include "consts.h"
9 #include "simplepdfi.h"
10 #include "autoonoff.h"
11 #include "hottypes.h"
12 #include "astfun.h"
14 #include <iostream>
15 #include <sstream>
16 #include <fstream>
17 #include <vector>
18 #include <stdio.h>
20 using namespace Shapes;
23 namespace Shapes
25 namespace Helpers
27 RefCountPtr< const Lang::TransparencyGroup >
28 newSolidTransparencyGroup( const RefCountPtr< const Lang::Drawable2D > & obj2, const RefCountPtr< const Lang::Drawable2D > & obj1 );
29 RefCountPtr< const Lang::TransparencyGroup >
30 newSolidTransparencyGroup( const RefCountPtr< const Lang::Drawable2D > & obj3, const RefCountPtr< const Lang::Drawable2D > & obj2, const RefCountPtr< const Lang::Drawable2D > & obj1 );
32 void stroke_helper_2D( Kernel::EvalState * evalState, const RefCountPtr< const Lang::ElementaryPath2D > & path, Kernel::Arguments & args, bool fill, const Ast::SourceLocation & callLoc );
33 void stroke_helper_3D( Kernel::EvalState * evalState, const RefCountPtr< const Lang::ElementaryPath3D > & path, Kernel::Arguments & args, bool fill, const Ast::SourceLocation & callLoc );
37 namespace Shapes
39 namespace Lang
42 class Core_spot : public Lang::CoreFunction
44 public:
45 Core_spot( const char * title ) : CoreFunction( title ) { }
46 virtual void
47 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
49 const size_t ARITY = 1;
50 CHECK_ARITY( args, ARITY, title_ );
52 typedef const Lang::Coords2D ArgType;
53 RefCountPtr< ArgType > p = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
55 ElementaryPath2D * pth = new ElementaryPath2D;
56 pth->push_back( new Concrete::PathPoint2D( p->x_.get( ), p->y_.get( ) ) );
57 if( Kernel::allowSingletonPaths )
59 pth->close( );
61 else
63 pth->push_back( new Concrete::PathPoint2D( p->x_.get( ), p->y_.get( ) ) );
66 Kernel::GraphicsState * capState( new Kernel::GraphicsState( *evalState->dyn_->getGraphicsState( ) ) );
67 capState->cap_ = Lang::CapStyle::CAP_ROUND;
69 Kernel::ContRef cont = evalState->cont_;
70 cont->takeValue( Kernel::ValueRef( new Lang::PaintedPath2D
71 ( RefCountPtr< const Kernel::GraphicsState >( capState ),
72 RefCountPtr< const Lang::ElementaryPath2D >( pth ),
73 "S" ) ),
74 evalState );
78 class Core_stroke : public Lang::CoreFunction
80 bool fill_;
81 public:
82 Core_stroke( const char * title, bool fill )
83 : CoreFunction( title, new Kernel::EvaluatedFormals( title, true ) ), fill_( fill )
85 formals_->appendEvaluatedCoreFormal( "path", Kernel::THE_SLOT_VARIABLE );
86 formals_->appendEvaluatedCoreFormal( "head", Kernel::VariableHandle( new Kernel::Variable( Lang::THE_NO_ARROW ) ) );
87 formals_->appendEvaluatedCoreFormal( "tail", Kernel::VariableHandle( new Kernel::Variable( Lang::THE_NO_ARROW ) ) );
90 virtual void
91 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
93 args.applyDefaults( );
95 try
97 typedef const Lang::ElementaryPath2D ArgType;
98 RefCountPtr< ArgType > arg = Helpers::elementaryPathTry2D( args.getValue( 0 ) );
99 Helpers::stroke_helper_2D( evalState, arg, args, fill_, callLoc );
100 return;
102 catch( const NonLocalExit::NotThisType & ball )
104 /* Wrong type; never mind!.. but see below!
110 typedef const Lang::ElementaryPath3D ArgType;
111 RefCountPtr< ArgType > arg = Helpers::elementaryPathTry3D( args.getValue( 0 ) );
112 Helpers::stroke_helper_3D( evalState, arg, args, fill_, callLoc );
113 return;
115 catch( const NonLocalExit::NotThisType & ball )
117 /* Wrong type; never mind!.. but see below!
121 const char * paintCmd = fill_ ? "B" : "S";
125 typedef const Lang::MultiPath2D ArgType;
126 RefCountPtr< ArgType > path = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) );
127 RefCountPtr< const Lang::Function > arrowHead = Helpers::down_cast_CoreArgument< const Lang::Function >( title_, args, 1, callLoc );
128 RefCountPtr< const Lang::Function > arrowTail = Helpers::down_cast_CoreArgument< const Lang::Function >( title_, args, 2, callLoc );
129 if( arrowHead != Lang::THE_NO_ARROW ||
130 arrowTail != Lang::THE_NO_ARROW )
132 throw Exceptions::MiscellaneousRequirement( strrefdup( "Arrowheads/tails are not supported for composite paths." ) );
134 Kernel::ContRef cont = evalState->cont_;
135 cont->takeValue( Kernel::ValueRef( new Lang::PaintedPath2D( evalState->dyn_->getGraphicsState( ), path, paintCmd ) ),
136 evalState );
137 return;
139 catch( const NonLocalExit::NotThisType & ball )
141 /* Wrong type; never mind!.. but see below!
147 typedef const Lang::MultiPath3D ArgType;
148 RefCountPtr< ArgType > path = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) );
149 RefCountPtr< const Lang::Function > arrowHead = Helpers::down_cast_CoreArgument< const Lang::Function >( title_, args, 1, callLoc );
150 RefCountPtr< const Lang::Function > arrowTail = Helpers::down_cast_CoreArgument< const Lang::Function >( title_, args, 2, callLoc );
151 if( arrowHead != Lang::THE_NO_ARROW ||
152 arrowTail != Lang::THE_NO_ARROW )
154 throw Exceptions::MiscellaneousRequirement( strrefdup( "Arrowheads/tails are not supported for composite paths." ) );
156 Kernel::ContRef cont = evalState->cont_;
157 cont->takeValue( Kernel::ValueRef( new Lang::PaintedPath3D( evalState->dyn_->getGraphicsState( ), path, paintCmd ) ),
158 evalState );
159 return;
161 catch( const NonLocalExit::NotThisType & ball )
163 /* Wrong type; never mind!.. but see below!
167 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::ElementaryPath2D::staticTypeName( ), Lang::ElementaryPath3D::staticTypeName( ) ) );
171 class Core_fill : public Lang::CoreFunction
173 public:
174 Core_fill( const char * title )
175 : CoreFunction( title, new Kernel::EvaluatedFormals( title, true ) )
177 formals_->appendEvaluatedCoreFormal( "path", Kernel::THE_SLOT_VARIABLE );
178 formals_->appendEvaluatedCoreFormal( "tiebreaker", Kernel::THE_VOID_VARIABLE );
181 virtual void
182 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
184 args.applyDefaults( );
186 RefCountPtr< const Lang::Length > tiebreaker = Helpers::down_cast_CoreArgument< const Lang::Length >( title_, args, 1, callLoc, true );
190 typedef const Lang::ElementaryPath2D ArgType;
191 RefCountPtr< ArgType > path = Helpers::elementaryPathTry2D( args.getValue( 0 ) );
192 if( tiebreaker != NullPtr< const Lang::Length >( ) )
194 throw Exceptions::CoreOutOfRange( title_, args, 1, "The tiebreaker may not specified for 2D paths." );
196 Kernel::ContRef cont = evalState->cont_;
197 cont->takeValue( Kernel::ValueRef( new Lang::PaintedPath2D( evalState->dyn_->getGraphicsState( ), path, "f" ) ),
198 evalState );
199 return;
201 catch( const NonLocalExit::NotThisType & ball )
203 /* Wrong type; never mind!.. but see below!
209 typedef const Lang::ElementaryPath3D ArgType;
210 RefCountPtr< ArgType > path = Helpers::elementaryPathTry3D( args.getValue( 0 ) );
211 Concrete::Length tiebreakerVal = Concrete::ZERO_LENGTH;
212 if( tiebreaker != NullPtr< const Lang::Length >( ) )
214 tiebreakerVal = tiebreaker->get( );
216 Kernel::ContRef cont = evalState->cont_;
217 cont->takeValue( Kernel::ValueRef( new Lang::PaintedPath3D( evalState->dyn_->getGraphicsState( ), path, "f", tiebreakerVal ) ),
218 evalState );
219 return;
221 catch( const NonLocalExit::NotThisType & ball )
223 /* Wrong type; never mind!.. but see below!
229 typedef const Lang::MultiPath2D ArgType;
230 RefCountPtr< ArgType > path = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) );
231 if( tiebreaker != NullPtr< const Lang::Length >( ) )
233 throw Exceptions::CoreOutOfRange( title_, args, 1, "The tiebreaker may not specified for 2D paths." );
235 Kernel::ContRef cont = evalState->cont_;
236 cont->takeValue( Kernel::ValueRef( new Lang::PaintedPath2D( evalState->dyn_->getGraphicsState( ), path, "f" ) ),
237 evalState );
238 return;
240 catch( const NonLocalExit::NotThisType & ball )
242 /* Wrong type; never mind!.. but see below!
248 typedef const Lang::MultiPath3D ArgType;
249 RefCountPtr< ArgType > path = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) );
250 Concrete::Length tiebreakerVal = Concrete::ZERO_LENGTH;
251 if( tiebreaker != NullPtr< const Lang::Length >( ) )
253 tiebreakerVal = tiebreaker->get( );
255 Kernel::ContRef cont = evalState->cont_;
256 cont->takeValue( Kernel::ValueRef( new Lang::PaintedPath3D( evalState->dyn_->getGraphicsState( ), path, "f", tiebreakerVal ) ),
257 evalState );
258 return;
260 catch( const NonLocalExit::NotThisType & ball )
262 /* Wrong type; never mind!.. but see below!
266 std::cerr << "Throwing in fill." << std::endl ;
267 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::MultiPath2D::staticTypeName( ), Lang::MultiPath3D::staticTypeName( ) ) );
271 class Core_fillstar : public Lang::CoreFunction
273 public:
274 Core_fillstar( const char * title ) : CoreFunction( title ) { }
275 virtual void
276 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
278 const size_t ARITY = 1;
279 CHECK_ARITY( args, ARITY, title_ );
283 typedef const Lang::ElementaryPath2D ArgType;
284 RefCountPtr< ArgType > path = Helpers::elementaryPathTry2D( args.getValue( 0 ) );
285 Kernel::ContRef cont = evalState->cont_;
286 cont->takeValue( Kernel::ValueRef( new Lang::PaintedPath2D( evalState->dyn_->getGraphicsState( ), path, "f*" ) ),
287 evalState );
288 return;
290 catch( const NonLocalExit::NotThisType & ball )
292 /* Wrong type; never mind!.. but see below!
298 typedef const Lang::MultiPath2D ArgType;
299 RefCountPtr< ArgType > path = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) );
300 Kernel::ContRef cont = evalState->cont_;
301 cont->takeValue( Kernel::ValueRef( new Lang::PaintedPath2D( evalState->dyn_->getGraphicsState( ), path, "f*" ) ),
302 evalState );
303 return;
305 catch( const NonLocalExit::NotThisType & ball )
307 /* Wrong type; never mind!.. but see below!
311 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::ElementaryPath2D::staticTypeName( ), Lang::MultiPath2D::staticTypeName( ) ) );
315 class Core_facetnormal : public Lang::CoreFunction
317 public:
318 Core_facetnormal( const char * title )
319 : CoreFunction( title, new Kernel::EvaluatedFormals( title, true ) )
321 formals_->appendEvaluatedCoreFormal( "location", Kernel::THE_SLOT_VARIABLE );
322 formals_->appendEvaluatedCoreFormal( "normal", Kernel::THE_SLOT_VARIABLE );
325 virtual void
326 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
328 args.applyDefaults( );
330 typedef const Lang::Coords3D LocationType;
331 typedef const Lang::FloatTriple NormalType;
333 RefCountPtr< LocationType > location = Helpers::down_cast_CoreArgument< LocationType >( title_, args, 0, callLoc, true );
334 RefCountPtr< NormalType > normal = Helpers::down_cast_CoreArgument< NormalType >( title_, args, 1, callLoc, true );
336 RefCountPtr< const Kernel::FacetState > facetState = evalState->dyn_->getFacetState( );
338 Kernel::ContRef cont = evalState->cont_;
340 RefCountPtr< const Lang::Color > nonStroking = evalState->dyn_->getGraphicsState( )->nonStrokingColor_;
342 /* If both @nonstroking and @autointensity are Gray, then we create a FacetNormalGray, otherwise colors are converted when needed to RGB so that we can create
343 * a FacetNormalRGB.
348 typedef const Lang::Gray ColorType;
349 RefCountPtr< ColorType > lightMultiply = Helpers::try_cast_CoreArgument< ColorType >( nonStroking );
351 cont->takeValue( Kernel::ValueRef( new Lang::FacetNormalGray( Concrete::Coords3D( location->x_.get( ),
352 location->y_.get( ),
353 location->z_.get( ) ),
354 facetState->reflections_,
355 Concrete::UnitFloatTriple( normal->x_, normal->y_, normal->z_ ),
356 lightMultiply->components( ),
357 facetState->autoScattering_,
358 Helpers::try_cast_CoreArgument< ColorType >( facetState->autoIntensity_ )->components( ) ) ),
359 evalState );
360 return;
362 catch( const NonLocalExit::NotThisType & ball )
364 /* Wrong type; never mind!.. but see below!
368 // When we reach here, we shall try to convert all colors to RGB.
370 typedef const Lang::RGB ColorType;
371 Concrete::RGB lightMultiply( 0, 0, 0 );
374 lightMultiply = Helpers::try_cast_CoreArgument< ColorType >( nonStroking )->components( );
375 goto doneMultiply;
377 catch( const NonLocalExit::NotThisType & ball )
379 /* Wrong type; never mind!.. but see below!
384 double a = Helpers::try_cast_CoreArgument< const Lang::Gray >( nonStroking )->components( ).gr_;
385 lightMultiply = Concrete::RGB( a, a, a );
386 goto doneMultiply;
388 catch( const NonLocalExit::NotThisType & ball )
390 /* Wrong type; never mind!.. but see below!
393 throw Exceptions::CoreDynamicTypeMismatch( callLoc, title_, Lang::DYNAMIC_VARIABLE_ID_NONSTROKING,
394 nonStroking->getTypeName( ),
395 Helpers::typeSetString( Lang::Gray::staticTypeName( ), Lang::RGB::staticTypeName( ) ) );
396 doneMultiply:
398 Concrete::RGB autoIntensity( 0, 0, 0 );
401 autoIntensity = Helpers::try_cast_CoreArgument< ColorType >( facetState->autoIntensity_ )->components( );
402 goto doneAuto;
404 catch( const NonLocalExit::NotThisType & ball )
406 /* Wrong type; never mind!.. but see below!
411 double a = Helpers::try_cast_CoreArgument< const Lang::Gray >( facetState->autoIntensity_ )->components( ).gr_;
412 autoIntensity = Concrete::RGB( a, a, a );
413 goto doneAuto;
415 catch( const NonLocalExit::NotThisType & ball )
417 /* Wrong type; never mind!.. but see below!
420 throw Exceptions::CoreDynamicTypeMismatch( callLoc, title_, Lang::DYNAMIC_VARIABLE_ID_AUTOINTENSITY,
421 nonStroking->getTypeName( ),
422 Helpers::typeSetString( Lang::Gray::staticTypeName( ), Lang::RGB::staticTypeName( ) ) );
423 doneAuto:
425 cont->takeValue( Kernel::ValueRef( new Lang::FacetNormalRGB( Concrete::Coords3D( location->x_.get( ),
426 location->y_.get( ),
427 location->z_.get( ) ),
428 facetState->reflections_,
429 Concrete::UnitFloatTriple( normal->x_, normal->y_, normal->z_ ),
430 lightMultiply,
431 facetState->autoScattering_,
432 autoIntensity ) ),
433 evalState );
434 return;
438 class Core_facet : public Lang::CoreFunction
440 public:
441 Core_facet( const char * title )
442 : CoreFunction( title, new Kernel::EvaluatedFormals( title, true ) )
444 formals_->appendEvaluatedCoreFormal( "path", Kernel::THE_SLOT_VARIABLE );
445 formals_->appendEvaluatedCoreFormal( "n1", Kernel::THE_VOID_VARIABLE );
446 formals_->appendEvaluatedCoreFormal( "n2", Kernel::THE_VOID_VARIABLE );
447 formals_->appendEvaluatedCoreFormal( "n3", Kernel::THE_VOID_VARIABLE );
448 formals_->appendEvaluatedCoreFormal( "tiebreaker", Kernel::VariableHandle( new Kernel::Variable( RefCountPtr< const Lang::Value >( new Lang::Length( Concrete::ZERO_LENGTH ) ) ) ) );
449 formals_->appendEvaluatedCoreFormal( "double", Kernel::THE_VOID_VARIABLE );
452 virtual void
453 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
455 args.applyDefaults( );
457 // Note that the <double> defaults to false if and only if there is at least one normal specifyed, and all normals agree on what is the outward normal.
459 typedef const Lang::ElementaryPath3D PathType;
460 typedef const Lang::FacetNormalGray GrayNormalType;
461 typedef const Lang::FacetNormalRGB RGBNormalType;
462 typedef const Lang::Length TiebreakerType;
463 typedef const Lang::Boolean DoubleSidedType;
465 RefCountPtr< PathType > path = Helpers::elementaryPathCast3D( title_, args, 0, callLoc );
467 bool isRGB = true;
468 bool foundColor = false;
469 size_t numNormals = 0;
470 RefCountPtr< GrayNormalType > nGray1 = RefCountPtr< GrayNormalType >( NullPtr< GrayNormalType >( ) );
471 RefCountPtr< GrayNormalType > nGray2 = RefCountPtr< GrayNormalType >( NullPtr< GrayNormalType >( ) );
472 RefCountPtr< GrayNormalType > nGray3 = RefCountPtr< GrayNormalType >( NullPtr< GrayNormalType >( ) );
473 RefCountPtr< RGBNormalType > nRGB1 = RefCountPtr< RGBNormalType >( NullPtr< RGBNormalType >( ) );
474 RefCountPtr< RGBNormalType > nRGB2 = RefCountPtr< RGBNormalType >( NullPtr< RGBNormalType >( ) );
475 RefCountPtr< RGBNormalType > nRGB3 = RefCountPtr< RGBNormalType >( NullPtr< RGBNormalType >( ) );
476 Concrete::UnitFloatTriple d1( 0, 0, 0, 1. );
477 Concrete::UnitFloatTriple d2( 0, 0, 0, 1. );
478 Concrete::UnitFloatTriple d3( 0, 0, 0, 1. );
481 typedef GrayNormalType NormalType;
482 nGray1 = Helpers::try_cast_CoreArgument< NormalType >( args.getValue( 1 ), true );
483 nGray2 = Helpers::try_cast_CoreArgument< NormalType >( args.getValue( 2 ), true );
484 nGray3 = Helpers::try_cast_CoreArgument< NormalType >( args.getValue( 3 ), true );
485 // If we reach here, numNormals will be zero.
486 if( nGray1 != NullPtr< NormalType >( ) )
488 d1 = nGray1->normal( );
489 ++numNormals;
491 if( nGray2 != NullPtr< NormalType >( ) )
493 if( numNormals < 1 )
495 throw Exceptions::CoreOutOfRange( title_, args, 2, "The normal n1 must be provided before providing n2." );
497 d2 = nGray2->normal( );
498 ++numNormals;
500 if( nGray3 != NullPtr< NormalType >( ) )
502 if( numNormals < 2 )
504 throw Exceptions::CoreOutOfRange( title_, args, 2, "The normals n1 and n2 must be provided before providing n3." );
506 d3 = nGray3->normal( );
507 ++numNormals;
509 foundColor = true;
510 isRGB = false;
512 catch( const NonLocalExit::NotThisType & ball )
514 /* Wrong type; never mind!.. but see below!
517 if( ! foundColor )
521 typedef RGBNormalType NormalType;
522 nRGB1 = Helpers::try_cast_CoreArgument< NormalType >( args.getValue( 1 ), true );
523 nRGB2 = Helpers::try_cast_CoreArgument< NormalType >( args.getValue( 2 ), true );
524 nRGB3 = Helpers::try_cast_CoreArgument< NormalType >( args.getValue( 3 ), true );
525 // If we reach here, numNormals will be zero.
526 if( nRGB1 != NullPtr< NormalType >( ) )
528 ++numNormals;
529 d1 = nRGB1->normal( );
531 if( nRGB2 != NullPtr< NormalType >( ) )
533 if( numNormals < 1 )
535 throw Exceptions::CoreOutOfRange( title_, args, 2, "The normal n1 must be provided before providing n2." );
537 ++numNormals;
538 d2 = nRGB2->normal( );
540 if( nRGB3 != NullPtr< NormalType >( ) )
542 if( numNormals < 2 )
544 throw Exceptions::CoreOutOfRange( title_, args, 2, "The normals n1 and n2 must be provided before providing n3." );
546 ++numNormals;
547 d3 = nRGB3->normal( );
549 foundColor = true;
551 catch( const NonLocalExit::NotThisType & ball )
553 /* Wrong type; never mind!.. but see below!
557 if( ! foundColor )
559 throw Exceptions::MiscellaneousRequirement( "The procided facet normals must either be all gray or all RGB." );
561 RefCountPtr< const Lang::Color > nonStroking = evalState->dyn_->getGraphicsState( )->nonStrokingColor_;
562 if( numNormals == 0 )
564 isRGB = dynamic_cast< const Lang::RGB * >( nonStroking.getPtr( ) ) != 0;
565 if( ! isRGB &&
566 dynamic_cast< const Lang::Gray * >( nonStroking.getPtr( ) ) == 0 )
568 throw Exceptions::CoreDynamicTypeMismatch( callLoc, title_, Lang::DYNAMIC_VARIABLE_ID_NONSTROKING,
569 nonStroking->getTypeName( ),
570 Helpers::typeSetString( Lang::Gray::staticTypeName( ), Lang::RGB::staticTypeName( ) ) );
574 RefCountPtr< TiebreakerType > tiebreaker = Helpers::down_cast_CoreArgument< TiebreakerType >( title_, args, 4, callLoc );
575 RefCountPtr< DoubleSidedType > doubleSided = Helpers::down_cast_CoreArgument< DoubleSidedType >( title_, args, 5, callLoc, true );
577 if( path->size( ) < 3 )
579 throw Exceptions::CoreOutOfRange( title_, args, 0, "A facet path must have at least 3 points." );
581 if( ! path->isClosed( ) )
583 throw Exceptions::CoreOutOfRange( title_, args, 0, "A facet path must be closed." );
586 for( PathType::const_iterator i = path->begin( ); i != path->end( ); ++i )
588 if( (*i)->front_ != (*i)->mid_ || (*i)->rear_ != (*i)->mid_ )
590 throw Exceptions::CoreOutOfRange( title_, args, 0, "A facet path must be a polygon." );
595 Kernel::ContRef cont = evalState->cont_;
597 Concrete::Coords3D p0( 0, 0, 0 );
598 Concrete::Coords3D p1( 0, 0, 0 );
599 Concrete::Coords3D p2( 0, 0, 0 );
600 path->getRepresentativePoints( Lang::THE_3D_IDENTITY, & p0, & p1, & p2 );
602 Concrete::UnitFloatTriple normal( 1., 0., 0., 1. );
605 normal = Concrete::crossDirection( p2 - p0, p1 - p0 );
607 catch( const NonLocalExit::CrossDirectionOfParallel & ball )
609 // This means that the crossDirection called failed because the vectors were parallel.
610 // A polygon of lower dimension is invisible, so we may just return an empty object.
611 cont->takeValue( Lang::THE_NULL3D,
612 evalState );
613 return;
616 bool isDoubleSided;
617 if( doubleSided != NullPtr< DoubleSidedType >( ) )
619 isDoubleSided = doubleSided->val_;
621 else
623 if( numNormals == 0 )
625 isDoubleSided = true;
627 else
629 bool allAgree = true;
630 bool n1Agree = Concrete::inner( normal, d1 ) > 0;
631 if( d2.normSquaredThatOughtToBeOne( ) > 0.5 )
633 allAgree = allAgree && ( ( Concrete::inner( normal, d2 ) > 0 ) == n1Agree );
635 if( d3.normSquaredThatOughtToBeOne( ) > 0.5 )
637 allAgree = allAgree && ( ( Concrete::inner( normal, d3 ) > 0 ) == n1Agree );
639 if( allAgree )
641 if( ! n1Agree )
643 normal = normal.reverse( );
645 isDoubleSided = false;
647 else
649 std::cerr << "Warning: A facet without explicitly specified double-sidedness had normals pointing in crazy directions, making it double sided." << std::endl ;
650 isDoubleSided = true;
655 if( isRGB )
657 typedef RGBNormalType NormalType;
658 RefCountPtr< NormalType > n1 = nRGB1;
659 RefCountPtr< NormalType > n2 = nRGB2;
660 RefCountPtr< NormalType > n3 = nRGB3;
661 RefCountPtr< const Computation::FacetInterpolatorRGB > interpolator = RefCountPtr< const Computation::FacetInterpolatorRGB >( NullPtr< const Computation::FacetInterpolatorRGB >( ) );
663 if( numNormals == 0 )
665 typedef const Lang::RGB ColorType;
666 RefCountPtr< ColorType > lightMultiply = Helpers::down_cast_CoreDynamic< ColorType >( title_, Lang::DYNAMIC_VARIABLE_ID_NONSTROKING, nonStroking, callLoc );
667 RefCountPtr< const Kernel::FacetState > facetState = evalState->dyn_->getFacetState( );
669 interpolator = RefCountPtr< const Computation::FacetInterpolatorRGB >
670 ( new Computation::FacetInterpolatorRGB1
671 ( RefCountPtr< const Lang::FacetNormalRGB >
672 ( new Lang::FacetNormalRGB
673 ( (1./3)*( p0 + p1 + p2 ),
674 facetState->reflections_,
675 normal,
676 lightMultiply->components( ),
677 facetState->autoScattering_,
678 Helpers::down_cast_CoreDynamic< ColorType >( title_, Lang::DYNAMIC_VARIABLE_ID_AUTOINTENSITY, facetState->autoIntensity_, callLoc )->components( ) ) ) ) );
680 else if( numNormals == 1 )
682 interpolator = RefCountPtr< const Computation::FacetInterpolatorRGB >
683 ( new Computation::FacetInterpolatorRGB1( n1 ) );
685 else if( numNormals == 2 )
687 interpolator = RefCountPtr< const Computation::FacetInterpolatorRGB >
688 ( new Computation::FacetInterpolatorRGB2( n1, n2 ) );
690 else if( numNormals == 3 )
692 interpolator = RefCountPtr< const Computation::FacetInterpolatorRGB >
693 ( new Computation::FacetInterpolatorRGB3( n1, n2, n3 ) );
695 else
697 throw Exceptions::InternalError( "Number of facet normals is out of range!" );
700 RefCountPtr< const Kernel::FacetState > facetState = evalState->dyn_->getFacetState( );
702 cont->takeValue( Kernel::ValueRef( new Lang::SingleSided3DRGB( path, interpolator,
703 ! isDoubleSided, // Note that this argument refers to single-sidedness
704 normal, Concrete::inner( normal, p0 ),
705 tiebreaker->get( ),
706 facetState->viewResolution_,
707 facetState->shadeOrder_ ) ),
708 evalState );
710 else // not isRGB
712 typedef GrayNormalType NormalType;
713 RefCountPtr< NormalType > n1 = nGray1;
714 RefCountPtr< NormalType > n2 = nGray2;
715 RefCountPtr< NormalType > n3 = nGray3;
716 RefCountPtr< const Computation::FacetInterpolatorGray > interpolator = RefCountPtr< const Computation::FacetInterpolatorGray >( NullPtr< const Computation::FacetInterpolatorGray >( ) );
718 if( numNormals == 0 )
720 typedef const Lang::Gray ColorType;
721 RefCountPtr< ColorType > lightMultiply = Helpers::down_cast_CoreDynamic< ColorType >( title_, Lang::DYNAMIC_VARIABLE_ID_NONSTROKING, nonStroking, callLoc );
722 RefCountPtr< const Kernel::FacetState > facetState = evalState->dyn_->getFacetState( );
724 interpolator = RefCountPtr< const Computation::FacetInterpolatorGray >
725 ( new Computation::FacetInterpolatorGray1
726 ( RefCountPtr< const Lang::FacetNormalGray >
727 ( new Lang::FacetNormalGray
728 ( (1./3)*( p0 + p1 + p2 ),
729 facetState->reflections_,
730 normal,
731 lightMultiply->components( ),
732 facetState->autoScattering_,
733 Helpers::down_cast_CoreDynamic< ColorType >( title_, Lang::DYNAMIC_VARIABLE_ID_AUTOINTENSITY, facetState->autoIntensity_, callLoc )->components( ) ) ) ) );
736 else if( numNormals == 1 )
738 interpolator = RefCountPtr< const Computation::FacetInterpolatorGray >
739 ( new Computation::FacetInterpolatorGray1( n1 ) );
741 else if( numNormals == 2 )
743 interpolator = RefCountPtr< const Computation::FacetInterpolatorGray >
744 ( new Computation::FacetInterpolatorGray2( n1, n2 ) );
746 else if( numNormals == 3 )
748 interpolator = RefCountPtr< const Computation::FacetInterpolatorGray >
749 ( new Computation::FacetInterpolatorGray3( n1, n2, n3 ) );
751 else
753 throw Exceptions::InternalError( "Number of facet normals is out of range!" );
756 RefCountPtr< const Kernel::FacetState > facetState = evalState->dyn_->getFacetState( );
758 cont->takeValue( Kernel::ValueRef( new Lang::SingleSided3DGray( path, interpolator,
759 ! isDoubleSided, // Note that this argument refers to single-sidedness
760 normal, Concrete::inner( normal, p0 ),
761 tiebreaker->get( ),
762 facetState->viewResolution_,
763 facetState->shadeOrder_ ) ),
764 evalState );
769 class Core_from3Dto2D : public Lang::CoreFunction
771 public:
772 Core_from3Dto2D( const char * title ) : CoreFunction( title ) { }
773 void
774 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
776 const size_t ARITY = 1;
777 CHECK_ARITY( args, ARITY, title_ );
779 typedef const Lang::Geometric3D ArgType;
780 RefCountPtr< ArgType > obj = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
782 Kernel::ContRef cont = evalState->cont_;
783 cont->takeValue( obj->to2D( evalState->dyn_, obj ),
784 evalState );
788 class Core_from2Dto3D : public Lang::CoreFunction
790 public:
791 Core_from2Dto3D( const char * title ) : CoreFunction( title ) { }
792 virtual void
793 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
795 const size_t ARITY = 1;
796 CHECK_ARITY( args, ARITY, title_ );
798 typedef const Lang::Geometric2D ArgType;
799 RefCountPtr< ArgType > obj = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
801 Kernel::ContRef cont = evalState->cont_;
802 cont->takeValue( obj->to3D( obj ),
803 evalState );
807 class Core_facing2Din3D : public Lang::CoreFunction
809 public:
810 Core_facing2Din3D( const char * title )
811 : CoreFunction( title, new Kernel::EvaluatedFormals( title, true ) )
813 formals_->appendEvaluatedCoreFormal( "obj", Kernel::THE_SLOT_VARIABLE );
814 formals_->appendEvaluatedCoreFormal( "scale", Kernel::VariableHandle( new Kernel::Variable( Lang::THE_FALSE ) ) );
815 formals_->appendEvaluatedCoreFormal( "distort", Kernel::VariableHandle( new Kernel::Variable( Lang::THE_FALSE ) ) );
817 virtual void
818 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
820 args.applyDefaults( );
824 typedef const Lang::Drawable2D ArgType;
825 Kernel::ContRef cont = evalState->cont_;
826 cont->takeValue( Kernel::ValueRef( new Lang::Facing2Din3D( Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) ),
827 Helpers::down_cast_CoreArgument< const Lang::Boolean >( title_, args, 1, callLoc )->val_,
828 Helpers::down_cast_CoreArgument< const Lang::Boolean >( title_, args, 2, callLoc )->val_ ) ),
829 evalState );
830 return;
832 catch( const NonLocalExit::NotThisType & ball )
834 /* Wrong type; never mind!.. but see below!
840 typedef const Lang::Function ArgType;
841 Kernel::ContRef cont = evalState->cont_;
842 /* The scale and distort arguments will simply be ignored.
844 cont->takeValue( Kernel::ValueRef( new Lang::FacingFunction3D( evalState->dyn_, Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ) ) ) ),
845 evalState );
846 return;
848 catch( const NonLocalExit::NotThisType & ball )
850 /* Wrong type; never mind!.. but see below!
854 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::Drawable2D::staticTypeName( ), Lang::Function::staticTypeName( ) ) );
858 class Core_bboxed : public Lang::CoreFunction
860 public:
861 Core_bboxed( const char * title ) : CoreFunction( title ) { }
862 virtual void
863 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
865 const size_t ARITY = 2;
866 CHECK_ARITY( args, ARITY, title_ );
868 size_t argsi = 0;
870 typedef const Lang::Drawable2D ArgType1;
871 RefCountPtr< ArgType1 > obj = Helpers::down_cast_CoreArgument< ArgType1 >( title_, args, argsi, callLoc );
873 ++argsi;
875 typedef const Lang::ElementaryPath2D ArgType2;
876 RefCountPtr< ArgType2 > p = Helpers::elementaryPathCast2D( title_, args, argsi, callLoc );
878 Kernel::ContRef cont = evalState->cont_;
879 cont->takeValue( Kernel::ValueRef( new Lang::BBoxed2D( obj, p ) ),
880 evalState );
884 class Core_clip : public Lang::CoreFunction
886 const char * clipCommand_;
887 public:
888 Core_clip( const char * title, const char * clipCommand ) : CoreFunction( title ), clipCommand_( clipCommand ) { }
889 virtual void
890 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
892 const size_t ARITY = 2;
893 CHECK_ARITY( args, ARITY, title_ );
895 size_t argsi = 0;
897 typedef const Lang::Drawable2D ArgType1;
898 RefCountPtr< ArgType1 > obj = Helpers::down_cast_CoreArgument< ArgType1 >( title_, args, argsi, callLoc );
900 RefCountPtr< Lang::Clipped2D > res( new Lang::Clipped2D( obj, clipCommand_ ) );
902 ++argsi;
905 typedef const Lang::ElementaryPath2D ArgType;
906 RefCountPtr< ArgType > path = Helpers::elementaryPathTry2D( args.getValue( argsi ) );
907 res->addSubPath( path );
908 goto done;
910 catch( const NonLocalExit::NotThisType & ball )
912 /* Wrong type; never mind!.. but see below!
918 typedef const Lang::SoftMask ArgType;
919 RefCountPtr< ArgType > mask = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( argsi ) );
920 Kernel::ContRef cont = evalState->cont_;
921 cont->takeValue( RefCountPtr< Lang::SoftMasked2D >( new Lang::SoftMasked2D( obj, mask ) ),
922 evalState );
923 return;
925 catch( const NonLocalExit::NotThisType & ball )
927 /* Wrong type; never mind!.. but see below!
933 typedef const Lang::MultiPath2D ArgType;
934 RefCountPtr< ArgType > path = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( argsi ) );
935 for( Lang::MultiPath2D::const_iterator i = path->begin( ); i != path->end( ); ++i )
938 typedef const Lang::ElementaryPath2D ArgType;
939 RefCountPtr< ArgType > subpath = (*i).down_cast< ArgType >( );
940 if( subpath != NullPtr< ArgType >( ) )
942 res->addSubPath( subpath );
943 continue;
948 typedef const Lang::Connection2D ArgType;
949 ArgType * subpath = dynamic_cast< ArgType * >( (*i).getPtr( ) );
950 if( subpath != 0 )
952 res->addSubPath( subpath->getElementaryPath( ) );
953 continue;
956 throw Exceptions::InternalError( "clip: Encountered a subpath of unexpected type" );
958 goto done;
960 catch( const NonLocalExit::NotThisType & ball )
962 /* Wrong type; never mind!.. but see below!
966 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::ElementaryPath2D::staticTypeName( ), Lang::MultiPath2D::staticTypeName( ) ) );
968 done:
969 Kernel::ContRef cont = evalState->cont_;
970 cont->takeValue( res,
971 evalState );
980 namespace Shapes
982 namespace Kernel
984 class ArrowheadReceiverFormals2D : public Kernel::EvaluatedFormals
986 public:
987 ArrowheadReceiverFormals2D( )
988 : Kernel::EvaluatedFormals( "< Arrowhead receiver >", true )
990 appendEvaluatedCoreFormal( "picture", Kernel::THE_SLOT_VARIABLE );
991 appendEvaluatedCoreFormal( "cut", Kernel::VariableHandle( new Kernel::Variable( RefCountPtr< const Lang::Value >( new Lang::Length( 0 ) ) ) ) );
995 ArrowheadReceiverFormals2D theArrowheadReceiverFormals2D;
997 class Stroke2DCont_tail : public Kernel::ForcedStructureContinuation
999 RefCountPtr< const Kernel::GraphicsState > graphicsState_;
1000 RefCountPtr< const Lang::ElementaryPath2D > path_;
1001 Kernel::PassedEnv env_;
1002 Kernel::PassedDyn dyn_;
1003 Kernel::ContRef cont_;
1004 public:
1005 Stroke2DCont_tail( const RefCountPtr< const Kernel::GraphicsState > & graphicsState, const RefCountPtr< const Lang::ElementaryPath2D > & path,
1006 const Kernel::PassedEnv & env, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1007 : Kernel::ForcedStructureContinuation( "Stroke's arrow tail receiver", traceLoc ), graphicsState_( graphicsState ), path_( path ), env_( env ), dyn_( dyn ), cont_( cont )
1009 virtual ~Stroke2DCont_tail( ) { }
1010 virtual void takeStructure( const RefCountPtr< const Lang::Structure > & structure, Kernel::EvalState * evalState ) const
1012 /* Argument 0: picture
1013 * Argument 1: cut
1015 Kernel::Arguments args( & theArrowheadReceiverFormals2D );
1016 structure->argList_->bind( & args, structure->values_, env_, dyn_ );
1017 args.applyDefaults( );
1019 typedef const Lang::Drawable2D ArgType0;
1020 RefCountPtr< ArgType0 > picture = Helpers::down_cast_CoreArgument< ArgType0 >( continuationName_, args, 0, traceLoc_ );
1022 typedef const Lang::Length ArgType1;
1023 RefCountPtr< ArgType1 > cutTail = Helpers::down_cast_CoreArgument< ArgType1 >( continuationName_, args, 1, traceLoc_ );
1025 if( cutTail->get( ) < 0 )
1027 throw Exceptions::MiscellaneousRequirement( strrefdup( "Arrow tail cut length was negative." ) );
1029 else if( cutTail->get( ) == 0 )
1031 cont_->takeValue( Helpers::newSolidTransparencyGroup( picture,
1032 RefCountPtr< const Lang::Drawable2D >( new Lang::PaintedPath2D( graphicsState_, path_, "S" ) ) ),
1033 evalState );
1035 else
1037 Concrete::SplineTime t1 = path_->arcTime( cutTail->get( ) );
1038 Concrete::SplineTime t2( HUGE_VAL );
1039 RefCountPtr< const Lang::ElementaryPath2D > subpath = path_->subpath( t1, t2 );
1040 if( ! subpath->empty( ) )
1042 cont_->takeValue( Helpers::newSolidTransparencyGroup( picture,
1043 RefCountPtr< const Lang::Drawable2D >( new Lang::PaintedPath2D( graphicsState_, subpath, "S" ) ) ),
1044 evalState );
1046 else
1048 cont_->takeValue( picture,
1049 evalState );
1054 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
1056 trace->push_front( Kernel::Continuation::BackTraceElem( this, "2D stroke's tail" ) );
1057 cont_->backTrace( trace );
1059 virtual void gcMark( Kernel::GCMarkedSet & marked )
1061 cont_->gcMark( marked );
1065 class Stroke2DCont_head : public Kernel::ForcedStructureContinuation
1067 RefCountPtr< const Kernel::GraphicsState > graphicsState_;
1068 RefCountPtr< const Lang::ElementaryPath2D > path_;
1069 Kernel::PassedEnv env_;
1070 Kernel::PassedDyn dyn_;
1071 Kernel::ContRef cont_;
1072 public:
1073 Stroke2DCont_head( const RefCountPtr< const Kernel::GraphicsState > & graphicsState, const RefCountPtr< const Lang::ElementaryPath2D > & path,
1074 const Kernel::PassedEnv & env, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1075 : Kernel::ForcedStructureContinuation( "Stroke's arrow tail receiver", traceLoc ), graphicsState_( graphicsState ), path_( path ), env_( env ), dyn_( dyn ), cont_( cont )
1077 virtual ~Stroke2DCont_head( ) { }
1078 virtual void takeStructure( const RefCountPtr< const Lang::Structure > & structure, Kernel::EvalState * evalState ) const
1080 /* Argument 0: picture
1081 * Argument 1: cut
1083 Kernel::Arguments args( & theArrowheadReceiverFormals2D );
1084 structure->argList_->bind( & args, structure->values_, env_, dyn_ );
1085 args.applyDefaults( );
1087 typedef const Lang::Drawable2D ArgType0;
1088 RefCountPtr< ArgType0 > picture = Helpers::down_cast_CoreArgument< ArgType0 >( continuationName_, args, 0, traceLoc_ );
1090 typedef const Lang::Length ArgType1;
1091 RefCountPtr< ArgType1 > cutHead = Helpers::down_cast_CoreArgument< ArgType1 >( continuationName_, args, 1, traceLoc_ );
1093 if( cutHead->get( ) < 0 )
1095 throw Exceptions::MiscellaneousRequirement( strrefdup( "Arrow head cut length was negative." ) );
1097 else if( cutHead->get( ) == 0 )
1099 cont_->takeValue( Helpers::newSolidTransparencyGroup( picture,
1100 RefCountPtr< const Lang::Drawable2D >( new Lang::PaintedPath2D( graphicsState_, path_, "S" ) ) ),
1101 evalState );
1103 else
1105 Concrete::SplineTime t1( 0 );
1106 Concrete::SplineTime t2 = path_->arcTime( path_->arcLength( ) - cutHead->get( ) );
1107 RefCountPtr< const Lang::ElementaryPath2D > subpath = path_->subpath( t1, t2 );
1108 if( ! subpath->empty( ) )
1110 cont_->takeValue( Helpers::newSolidTransparencyGroup( picture,
1111 RefCountPtr< const Lang::Drawable2D >( new Lang::PaintedPath2D( graphicsState_, subpath, "S" ) ) ),
1112 evalState );
1114 else
1116 cont_->takeValue( picture,
1117 evalState );
1121 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
1123 trace->push_front( Kernel::Continuation::BackTraceElem( this, "2D stroke's head" ) );
1124 cont_->backTrace( trace );
1126 virtual void gcMark( Kernel::GCMarkedSet & marked )
1128 cont_->gcMark( marked );
1132 class Stroke2DCont_both2 : public Kernel::ForcedStructureContinuation
1134 RefCountPtr< const Kernel::GraphicsState > graphicsState_;
1135 RefCountPtr< const Lang::ElementaryPath2D > path_;
1136 RefCountPtr< const Lang::Drawable2D > tail_;
1137 Lang::Length cutTail_;
1138 Kernel::PassedEnv env_;
1139 Kernel::PassedDyn dyn_;
1140 Kernel::ContRef cont_;
1141 public:
1142 Stroke2DCont_both2( const RefCountPtr< const Kernel::GraphicsState > & graphicsState, const RefCountPtr< const Lang::ElementaryPath2D > & path,
1143 const RefCountPtr< const Lang::Drawable2D > & tail, Lang::Length cutTail,
1144 const Kernel::PassedEnv & env, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1145 : Kernel::ForcedStructureContinuation( "Stroke's arrow head receiver", traceLoc ), graphicsState_( graphicsState ), path_( path ), tail_( tail ), cutTail_( cutTail ), env_( env ), dyn_( dyn ), cont_( cont )
1147 virtual ~Stroke2DCont_both2( ) { }
1148 virtual void takeStructure( const RefCountPtr< const Lang::Structure > & structure, Kernel::EvalState * evalState ) const
1150 /* Argument 0: picture
1151 * Argument 1: cut
1153 Kernel::Arguments args( & theArrowheadReceiverFormals2D );
1154 structure->argList_->bind( & args, structure->values_, env_, dyn_ );
1155 args.applyDefaults( );
1157 typedef const Lang::Drawable2D ArgType0;
1158 RefCountPtr< ArgType0 > picture = Helpers::down_cast_CoreArgument< ArgType0 >( continuationName_, args, 0, traceLoc_ );
1160 typedef const Lang::Length ArgType1;
1161 RefCountPtr< ArgType1 > cutHead = Helpers::down_cast_CoreArgument< ArgType1 >( continuationName_, args, 1, traceLoc_ );
1163 if( cutHead->get( ) < 0 )
1165 throw Exceptions::MiscellaneousRequirement( strrefdup( "Aarrow head cut length was negative." ) );
1168 if( cutTail_.get( ) == 0 && cutHead->get( ) == 0 )
1170 cont_->takeValue( Helpers::newSolidTransparencyGroup( picture,
1171 tail_,
1172 RefCountPtr< const Lang::Drawable2D >( new Lang::PaintedPath2D( graphicsState_, path_, "S" ) ) ),
1173 evalState );
1175 else
1177 Concrete::SplineTime t1( 0 );
1178 if( cutTail_.get( ) > 0 )
1180 t1 = path_->arcTime( cutTail_.get( ) );
1183 Concrete::SplineTime t2( HUGE_VAL );
1184 if( cutHead->get( ) > 0 )
1186 t2 = path_->arcTime( path_->arcLength( ) - cutHead->get( ) );
1189 RefCountPtr< const Lang::ElementaryPath2D > subpath = path_->subpath( t1, t2 );
1191 if( ! subpath->empty( ) )
1193 cont_->takeValue( Helpers::newSolidTransparencyGroup( picture,
1194 tail_,
1195 RefCountPtr< const Lang::Drawable2D >( new Lang::PaintedPath2D( graphicsState_, subpath, "S" ) ) ),
1196 evalState );
1198 else
1200 cont_->takeValue( Helpers::newSolidTransparencyGroup( picture,
1201 tail_ ),
1202 evalState );
1206 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
1208 trace->push_front( Kernel::Continuation::BackTraceElem( this, "2D stroke's head & tail, second" ) );
1209 cont_->backTrace( trace );
1211 virtual void gcMark( Kernel::GCMarkedSet & marked )
1213 const_cast< Lang::Drawable2D * >( tail_.getPtr( ) )->gcMark( marked );
1214 cont_->gcMark( marked );
1218 class Stroke2DCont_both1 : public Kernel::ForcedStructureContinuation
1220 RefCountPtr< const Kernel::GraphicsState > graphicsState_;
1221 RefCountPtr< const Lang::ElementaryPath2D > path_;
1222 RefCountPtr< const Lang::Function > headFunction_;
1223 Kernel::PassedEnv env_;
1224 Kernel::PassedDyn dyn_;
1225 Kernel::ContRef cont_;
1226 public:
1227 Stroke2DCont_both1( const RefCountPtr< const Kernel::GraphicsState > & graphicsState, const RefCountPtr< const Lang::ElementaryPath2D > & path,
1228 const RefCountPtr< const Lang::Function > & headFunction,
1229 const Kernel::PassedEnv & env, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1230 : Kernel::ForcedStructureContinuation( "Stroke's arrow tail receiver", traceLoc ), graphicsState_( graphicsState ), path_( path ), headFunction_( headFunction ), env_( env ), dyn_( dyn ), cont_( cont )
1232 virtual ~Stroke2DCont_both1( ) { }
1233 virtual void takeStructure( const RefCountPtr< const Lang::Structure > & structure, Kernel::EvalState * evalState ) const
1235 /* Argument 0: picture
1236 * Argument 1: cut
1238 Kernel::Arguments args( & theArrowheadReceiverFormals2D );
1239 structure->argList_->bind( & args, structure->values_, env_, dyn_ );
1240 args.applyDefaults( );
1242 typedef const Lang::Drawable2D ArgType0;
1243 RefCountPtr< ArgType0 > picture = Helpers::down_cast_CoreArgument< ArgType0 >( continuationName_, args, 0, traceLoc_ );
1245 typedef const Lang::Length ArgType1;
1246 RefCountPtr< ArgType1 > cutTail = Helpers::down_cast_CoreArgument< ArgType1 >( continuationName_, args, 1, traceLoc_ );
1248 if( cutTail->get( ) < 0 )
1250 throw Exceptions::MiscellaneousRequirement( strrefdup( "Arrow tail cut length was negative." ) );
1253 evalState->env_ = env_;
1254 evalState->dyn_ = dyn_;
1255 evalState->cont_ = Kernel::ContRef( new Kernel::Stroke2DCont_both2( graphicsState_, path_, picture, *cutTail, env_, dyn_, cont_, traceLoc_ ) );
1256 headFunction_->call( evalState, path_->reverse( ), traceLoc_ );
1258 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
1260 trace->push_front( Kernel::Continuation::BackTraceElem( this, "2D stroke's head & tail, first" ) );
1261 cont_->backTrace( trace );
1263 virtual void gcMark( Kernel::GCMarkedSet & marked )
1265 const_cast< Lang::Function * >( headFunction_.getPtr( ) )->gcMark( marked );
1266 dyn_->gcMark( marked );
1267 cont_->gcMark( marked );
1276 void
1277 Helpers::stroke_helper_2D( Kernel::EvalState * evalState, const RefCountPtr< const Lang::ElementaryPath2D > & path, Kernel::Arguments & args, bool fill, const Ast::SourceLocation & callLoc )
1279 RefCountPtr< const Lang::Function > arrowHead = args.getHandle( 1 )->getVal< const Lang::Function >( "< core function stroke: head >" );
1280 RefCountPtr< const Lang::Function > arrowTail = args.getHandle( 2 )->getVal< const Lang::Function >( "< core function stroke: tail >" );
1281 if( ( arrowHead == Lang::THE_NO_ARROW &&
1282 arrowTail == Lang::THE_NO_ARROW ) ||
1283 path->size( ) < 2 )
1285 Kernel::ContRef cont = evalState->cont_;
1286 cont->takeValue( Kernel::ValueRef( new Lang::PaintedPath2D( evalState->dyn_->getGraphicsState( ), path, fill ? "B" : "S" ) ),
1287 evalState );
1288 return;
1290 else
1292 /* The computation must continue outside here since functions are to be called, and resulting graphics collected.
1294 if( fill )
1296 throw Exceptions::NotImplemented( "Arrowheads in fill-stroke command." );
1299 if( arrowTail == Lang::THE_NO_ARROW )
1301 /* There's only an arrow at the head.
1303 evalState->cont_ = Kernel::ContRef( new Kernel::Stroke2DCont_head( evalState->dyn_->getGraphicsState( ), path, evalState->env_, evalState->dyn_, evalState->cont_, callLoc ) );
1304 arrowHead->call( evalState, path->reverse( ), callLoc );
1305 return;
1308 if( arrowHead == Lang::THE_NO_ARROW )
1310 /* There's only an arrow at the tail.
1312 evalState->cont_ = Kernel::ContRef( new Kernel::Stroke2DCont_tail( evalState->dyn_->getGraphicsState( ), path, evalState->env_, evalState->dyn_, evalState->cont_, callLoc ) );
1313 arrowHead->call( arrowTail, evalState, args.getHandle( 0 ), callLoc );
1314 return;
1317 evalState->cont_ = Kernel::ContRef( new Kernel::Stroke2DCont_both1( evalState->dyn_->getGraphicsState( ), path, arrowHead, evalState->env_, evalState->dyn_, evalState->cont_, callLoc ) );
1318 arrowTail->call( arrowTail, evalState, args.getHandle( 0 ), callLoc );
1319 return;
1324 namespace Shapes
1326 namespace Kernel
1328 class ArrowheadReceiverFormals3D : public Kernel::EvaluatedFormals
1330 public:
1331 ArrowheadReceiverFormals3D( )
1332 : Kernel::EvaluatedFormals( "< Arrowhead receiver >", true )
1334 appendEvaluatedCoreFormal( "picture", Kernel::THE_SLOT_VARIABLE );
1335 appendEvaluatedCoreFormal( "cut", Kernel::VariableHandle( new Kernel::Variable( RefCountPtr< const Lang::Value >( new Lang::Length( 0 ) ) ) ) );
1339 ArrowheadReceiverFormals3D theArrowheadReceiverFormals3D;
1341 class Stroke3DCont_tail : public Kernel::ForcedStructureContinuation
1343 RefCountPtr< const Kernel::GraphicsState > graphicsState_;
1344 RefCountPtr< const Lang::ElementaryPath3D > path_;
1345 Kernel::PassedEnv env_;
1346 Kernel::PassedDyn dyn_;
1347 Kernel::ContRef cont_;
1348 public:
1349 Stroke3DCont_tail( const RefCountPtr< const Kernel::GraphicsState > & graphicsState, const RefCountPtr< const Lang::ElementaryPath3D > & path,
1350 const Kernel::PassedEnv & env, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1351 : Kernel::ForcedStructureContinuation( "Stroke's arrow tail receiver", traceLoc ), graphicsState_( graphicsState ), path_( path ), env_( env ), dyn_( dyn ), cont_( cont )
1353 virtual ~Stroke3DCont_tail( ) { }
1354 virtual void takeStructure( const RefCountPtr< const Lang::Structure > & structure, Kernel::EvalState * evalState ) const
1356 /* Argument 0: picture
1357 * Argument 1: cut
1359 Kernel::Arguments args( & theArrowheadReceiverFormals3D );
1360 structure->argList_->bind( & args, structure->values_, env_, dyn_ );
1361 args.applyDefaults( );
1363 typedef const Lang::Drawable3D ArgType0;
1364 RefCountPtr< ArgType0 > picture = Helpers::down_cast_CoreArgument< ArgType0 >( continuationName_, args, 0, traceLoc_ );
1366 typedef const Lang::Length ArgType1;
1367 RefCountPtr< ArgType1 > cutTail = Helpers::down_cast_CoreArgument< ArgType1 >( continuationName_, args, 1, traceLoc_ );
1369 if( cutTail->get( ) < 0 )
1371 throw Exceptions::MiscellaneousRequirement( strrefdup( "Arrow tail cut length was negative." ) );
1373 else if( cutTail->get( ) == 0 )
1375 cont_->takeValue( Helpers::newGroup3D( evalState->dyn_->getGraphicsState( ),
1376 picture,
1377 RefCountPtr< const Lang::Drawable3D >( new Lang::PaintedPath3D( graphicsState_, path_, "S" ) ) ),
1378 evalState );
1380 else
1382 Concrete::SplineTime t1 = path_->arcTime( cutTail->get( ) );
1383 Concrete::SplineTime t2( HUGE_VAL );
1384 RefCountPtr< const Lang::ElementaryPath3D > subpath = path_->subpath( t1, t2 );
1385 if( ! subpath->empty( ) )
1387 cont_->takeValue( Helpers::newGroup3D( evalState->dyn_->getGraphicsState( ),
1388 picture,
1389 RefCountPtr< const Lang::Drawable3D >( new Lang::PaintedPath3D( graphicsState_, subpath, "S" ) ) ),
1390 evalState );
1392 else
1394 cont_->takeValue( picture,
1395 evalState );
1400 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
1402 trace->push_front( Kernel::Continuation::BackTraceElem( this, "3D stroke's tail" ) );
1403 cont_->backTrace( trace );
1405 virtual void gcMark( Kernel::GCMarkedSet & marked )
1407 cont_->gcMark( marked );
1411 class Stroke3DCont_head : public Kernel::ForcedStructureContinuation
1413 RefCountPtr< const Kernel::GraphicsState > graphicsState_;
1414 RefCountPtr< const Lang::ElementaryPath3D > path_;
1415 Kernel::PassedEnv env_;
1416 Kernel::PassedDyn dyn_;
1417 Kernel::ContRef cont_;
1418 public:
1419 Stroke3DCont_head( const RefCountPtr< const Kernel::GraphicsState > & graphicsState, const RefCountPtr< const Lang::ElementaryPath3D > & path,
1420 const Kernel::PassedEnv & env, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1421 : Kernel::ForcedStructureContinuation( "Stroke's arrow tail receiver", traceLoc ), graphicsState_( graphicsState ), path_( path ), env_( env ), dyn_( dyn ), cont_( cont )
1423 virtual ~Stroke3DCont_head( ) { }
1424 virtual void takeStructure( const RefCountPtr< const Lang::Structure > & structure, Kernel::EvalState * evalState ) const
1426 /* Argument 0: picture
1427 * Argument 1: cut
1429 Kernel::Arguments args( & theArrowheadReceiverFormals3D );
1430 structure->argList_->bind( & args, structure->values_, env_, dyn_ );
1431 args.applyDefaults( );
1433 typedef const Lang::Drawable3D ArgType0;
1434 RefCountPtr< ArgType0 > picture = Helpers::down_cast_CoreArgument< ArgType0 >( continuationName_, args, 0, traceLoc_ );
1436 typedef const Lang::Length ArgType1;
1437 RefCountPtr< ArgType1 > cutHead = Helpers::down_cast_CoreArgument< ArgType1 >( continuationName_, args, 1, traceLoc_ );
1439 if( cutHead->get( ) < 0 )
1441 throw Exceptions::MiscellaneousRequirement( strrefdup( "Arrow head cut length was negative." ) );
1443 else if( cutHead->get( ) == 0 )
1445 cont_->takeValue( Helpers::newGroup3D( evalState->dyn_->getGraphicsState( ),
1446 picture,
1447 RefCountPtr< const Lang::Drawable3D >( new Lang::PaintedPath3D( graphicsState_, path_, "S" ) ) ),
1448 evalState );
1450 else
1452 Concrete::SplineTime t1( 0 );
1453 Concrete::SplineTime t2 = path_->arcTime( path_->arcLength( ) - cutHead->get( ) );
1454 RefCountPtr< const Lang::ElementaryPath3D > subpath = path_->subpath( t1, t2 );
1455 if( ! subpath->empty( ) )
1457 cont_->takeValue( Helpers::newGroup3D( evalState->dyn_->getGraphicsState( ),
1458 picture,
1459 RefCountPtr< const Lang::Drawable3D >( new Lang::PaintedPath3D( graphicsState_, subpath, "S" ) ) ),
1460 evalState );
1462 else
1464 cont_->takeValue( picture,
1465 evalState );
1469 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
1471 trace->push_front( Kernel::Continuation::BackTraceElem( this, "3D stroke's head" ) );
1472 cont_->backTrace( trace );
1474 virtual void gcMark( Kernel::GCMarkedSet & marked )
1476 cont_->gcMark( marked );
1480 class Stroke3DCont_both2 : public Kernel::ForcedStructureContinuation
1482 RefCountPtr< const Kernel::GraphicsState > graphicsState_;
1483 RefCountPtr< const Lang::ElementaryPath3D > path_;
1484 RefCountPtr< const Lang::Drawable3D > tail_;
1485 Lang::Length cutTail_;
1486 Kernel::PassedEnv env_;
1487 Kernel::PassedDyn dyn_;
1488 Kernel::ContRef cont_;
1489 public:
1490 Stroke3DCont_both2( const RefCountPtr< const Kernel::GraphicsState > & graphicsState, const RefCountPtr< const Lang::ElementaryPath3D > & path,
1491 const RefCountPtr< const Lang::Drawable3D > & tail, Lang::Length cutTail,
1492 const Kernel::PassedEnv & env, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1493 : Kernel::ForcedStructureContinuation( "Stroke's arrow head receiver", traceLoc ), graphicsState_( graphicsState ), path_( path ), tail_( tail ), cutTail_( cutTail ), env_( env ), dyn_( dyn ), cont_( cont )
1495 virtual ~Stroke3DCont_both2( ) { }
1496 virtual void takeStructure( const RefCountPtr< const Lang::Structure > & structure, Kernel::EvalState * evalState ) const
1498 /* Argument 0: picture
1499 * Argument 1: cut
1501 Kernel::Arguments args( & theArrowheadReceiverFormals3D );
1502 structure->argList_->bind( & args, structure->values_, env_, dyn_ );
1503 args.applyDefaults( );
1505 typedef const Lang::Drawable3D ArgType0;
1506 RefCountPtr< ArgType0 > picture = Helpers::down_cast_CoreArgument< ArgType0 >( continuationName_, args, 0, traceLoc_ );
1508 typedef const Lang::Length ArgType1;
1509 RefCountPtr< ArgType1 > cutHead = Helpers::down_cast_CoreArgument< ArgType1 >( continuationName_, args, 1, traceLoc_ );
1511 if( cutHead->get( ) < 0 )
1513 throw Exceptions::MiscellaneousRequirement( strrefdup( "Aarrow head cut length was negative." ) );
1516 if( cutTail_.get( ) == 0 && cutHead->get( ) == 0 )
1518 cont_->takeValue( Helpers::newGroup3D( evalState->dyn_->getGraphicsState( ),
1519 picture,
1520 tail_,
1521 RefCountPtr< const Lang::Drawable3D >( new Lang::PaintedPath3D( graphicsState_, path_, "S" ) ) ),
1522 evalState );
1524 else
1526 Concrete::SplineTime t1( 0 );
1527 if( cutTail_.get( ) > 0 )
1529 t1 = path_->arcTime( cutTail_.get( ) );
1532 Concrete::SplineTime t2( HUGE_VAL );
1533 if( cutHead->get( ) > 0 )
1535 t2 = path_->arcTime( path_->arcLength( ) - cutHead->get( ) );
1538 RefCountPtr< const Lang::ElementaryPath3D > subpath = path_->subpath( t1, t2 );
1540 if( ! subpath->empty( ) )
1542 cont_->takeValue( Helpers::newGroup3D( evalState->dyn_->getGraphicsState( ),
1543 picture,
1544 tail_,
1545 RefCountPtr< const Lang::Drawable3D >( new Lang::PaintedPath3D( graphicsState_, subpath, "S" ) ) ),
1546 evalState );
1548 else
1550 cont_->takeValue( Helpers::newGroup3D( evalState->dyn_->getGraphicsState( ),
1551 picture,
1552 tail_ ),
1553 evalState );
1557 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
1559 trace->push_front( Kernel::Continuation::BackTraceElem( this, "3D stroke's head & tail, second" ) );
1560 cont_->backTrace( trace );
1562 virtual void gcMark( Kernel::GCMarkedSet & marked )
1564 const_cast< Lang::Drawable3D * >( tail_.getPtr( ) )->gcMark( marked );
1565 cont_->gcMark( marked );
1569 class Stroke3DCont_both1 : public Kernel::ForcedStructureContinuation
1571 RefCountPtr< const Kernel::GraphicsState > graphicsState_;
1572 RefCountPtr< const Lang::ElementaryPath3D > path_;
1573 RefCountPtr< const Lang::Function > headFunction_;
1574 Kernel::PassedEnv env_;
1575 Kernel::PassedDyn dyn_;
1576 Kernel::ContRef cont_;
1577 public:
1578 Stroke3DCont_both1( const RefCountPtr< const Kernel::GraphicsState > & graphicsState, const RefCountPtr< const Lang::ElementaryPath3D > & path,
1579 const RefCountPtr< const Lang::Function > & headFunction,
1580 const Kernel::PassedEnv & env, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1581 : Kernel::ForcedStructureContinuation( "Stroke's arrow tail receiver", traceLoc ), graphicsState_( graphicsState ), path_( path ), headFunction_( headFunction ), env_( env ), dyn_( dyn ), cont_( cont )
1583 virtual ~Stroke3DCont_both1( ) { }
1584 virtual void takeStructure( const RefCountPtr< const Lang::Structure > & structure, Kernel::EvalState * evalState ) const
1586 /* Argument 0: picture
1587 * Argument 1: cut
1589 Kernel::Arguments args( & theArrowheadReceiverFormals3D );
1590 structure->argList_->bind( & args, structure->values_, env_, dyn_ );
1591 args.applyDefaults( );
1593 typedef const Lang::Drawable3D ArgType0;
1594 RefCountPtr< ArgType0 > picture = Helpers::down_cast_CoreArgument< ArgType0 >( continuationName_, args, 0, traceLoc_ );
1596 typedef const Lang::Length ArgType1;
1597 RefCountPtr< ArgType1 > cutTail = Helpers::down_cast_CoreArgument< ArgType1 >( continuationName_, args, 1, traceLoc_ );
1599 if( cutTail->get( ) < 0 )
1601 throw Exceptions::MiscellaneousRequirement( strrefdup( "Arrow tail cut length was negative." ) );
1604 evalState->env_ = env_;
1605 evalState->dyn_ = dyn_;
1606 evalState->cont_ = Kernel::ContRef( new Kernel::Stroke3DCont_both2( graphicsState_, path_, picture, *cutTail, env_, dyn_, cont_, traceLoc_ ) );
1607 headFunction_->call( evalState, path_->reverse( ), traceLoc_ );
1609 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
1611 trace->push_front( Kernel::Continuation::BackTraceElem( this, "3D stroke's head & tail, first" ) );
1612 cont_->backTrace( trace );
1614 virtual void gcMark( Kernel::GCMarkedSet & marked )
1616 const_cast< Lang::Function * >( headFunction_.getPtr( ) )->gcMark( marked );
1617 dyn_->gcMark( marked );
1618 cont_->gcMark( marked );
1626 void
1627 Helpers::stroke_helper_3D( Kernel::EvalState * evalState, const RefCountPtr< const Lang::ElementaryPath3D > & path, Kernel::Arguments & args, bool fill, const Ast::SourceLocation & callLoc )
1629 RefCountPtr< const Lang::Function > arrowHead = args.getHandle( 1 )->getVal< const Lang::Function >( "< core function stroke: head >" );
1630 RefCountPtr< const Lang::Function > arrowTail = args.getHandle( 2 )->getVal< const Lang::Function >( "< core function stroke: tail >" );
1631 if( ( arrowHead == Lang::THE_NO_ARROW &&
1632 arrowTail == Lang::THE_NO_ARROW ) ||
1633 path->size( ) < 2 )
1635 Kernel::ContRef cont = evalState->cont_;
1636 cont->takeValue( Kernel::ValueRef( new Lang::PaintedPath3D( evalState->dyn_->getGraphicsState( ), path, fill ? "B" : "S" ) ),
1637 evalState );
1638 return;
1640 else
1642 /* The computation must continue outside here since functions are to be called, and resulting graphics collected.
1644 if( fill )
1646 throw Exceptions::NotImplemented( "Arrowheads in fill-stroke command." );
1649 if( arrowTail == Lang::THE_NO_ARROW )
1651 /* There's only an arrow at the head.
1653 evalState->cont_ = Kernel::ContRef( new Kernel::Stroke3DCont_head( evalState->dyn_->getGraphicsState( ), path, evalState->env_, evalState->dyn_, evalState->cont_, callLoc ) );
1654 arrowHead->call( evalState, path->reverse( ), callLoc );
1655 return;
1658 if( arrowHead == Lang::THE_NO_ARROW )
1660 /* There's only an arrow at the tail.
1662 evalState->cont_ = Kernel::ContRef( new Kernel::Stroke3DCont_tail( evalState->dyn_->getGraphicsState( ), path, evalState->env_, evalState->dyn_, evalState->cont_, callLoc ) );
1663 arrowHead->call( arrowTail, evalState, args.getHandle( 0 ), callLoc );
1664 return;
1667 evalState->cont_ = Kernel::ContRef( new Kernel::Stroke3DCont_both1( evalState->dyn_->getGraphicsState( ), path, arrowHead, evalState->env_, evalState->dyn_, evalState->cont_, callLoc ) );
1668 arrowTail->call( arrowTail, evalState, args.getHandle( 0 ), callLoc );
1669 return;
1679 void
1680 Kernel::registerCore_draw( Kernel::Environment * env )
1682 env->initDefineCoreFunction( new Lang::Core_spot( "spot" ) );
1683 env->initDefineCoreFunction( new Lang::Core_stroke( "stroke", false ) );
1684 env->initDefineCoreFunction( new Lang::Core_stroke( "fillstroke", true ) );
1685 env->initDefineCoreFunction( new Lang::Core_fill( "fill" ) );
1686 env->initDefineCoreFunction( new Lang::Core_fillstar( "fillodd" ) );
1687 env->initDefineCoreFunction( new Lang::Core_facetnormal( "facetnormal" ) );
1688 env->initDefineCoreFunction( new Lang::Core_facet( "facet" ) );
1690 env->initDefineCoreFunction( new Lang::Core_bboxed( "bboxed" ) );
1691 env->initDefineCoreFunction( new Lang::Core_clip( "clip", "W" ) );
1692 env->initDefineCoreFunction( new Lang::Core_clip( "clipodd", "W*" ) );
1694 env->initDefineCoreFunction( new Lang::Core_from3Dto2D( "view" ) );
1695 env->initDefineCoreFunction( new Lang::Core_from2Dto3D( "immerse" ) );
1696 env->initDefineCoreFunction( new Lang::Core_facing2Din3D( "facing" ) );