Update suitable examples and tests to use blank mode
[shapes.git] / source / dynamicenvironment.cc
blob34510788b618b9912791554ee20d58e796a500cc
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, 2010, 2014 Henrik Tidefelt
19 #include <cmath>
21 #include "Shapes_Helpers_decls.h"
23 #include "dynamicenvironment.h"
24 #include "hottypes.h"
25 #include "globals.h"
26 #include "shapescore.h"
27 #include "ast.h"
28 #include "astvar.h"
29 #include "isnan.h"
30 #include "continuations.h"
31 #include "check.h"
33 #include <limits>
34 #include <iomanip>
36 using namespace Shapes;
39 void
40 Kernel::SpecialUnitVariables::specialUnitService( Concrete::Length * d, double * a0, double * a1 )
42 if( p0_ == 0 || p1_ == 0 )
44 throw Exceptions::InternalError( "The path points were not setup before calling specialUnitService" );
46 Concrete::Length x0;
47 Concrete::Length y0;
48 Concrete::Length x3;
49 Concrete::Length y3;
50 double ag0; /* global angles that will later be compared with aRef */
51 double ag1;
53 if( reverseDirection_ )
55 x0 = p1_->mid_->x_;
56 y0 = p1_->mid_->y_;
57 x3 = p0_->mid_->x_;
58 y3 = p0_->mid_->y_;
59 ag0 = p1_->rearAngle_;
60 ag1 = p0_->frontAngle_;
62 else
64 x0 = p0_->mid_->x_;
65 y0 = p0_->mid_->y_;
66 x3 = p1_->mid_->x_;
67 y3 = p1_->mid_->y_;
68 ag0 = p0_->frontAngle_;
69 ag1 = p1_->rearAngle_;
72 Concrete::Length dx = x3 - x0;
73 Concrete::Length dy = y3 - y0;
75 *d = hypotPhysical( dx, dy );
77 double aRef = atan2( dy.offtype< 1, 0 >( ), dx.offtype< 1, 0 >( ) ); /* Angles will be relative to the angle pointing to the other mid point */
79 if( p0_->frontState_ & Concrete::PathPoint2D::FREE_ANGLE )
81 throw Exceptions::InternalError( "Found a free angle in specialUnitService." );
84 if( p1_->rearState_ & Concrete::PathPoint2D::FREE_ANGLE )
86 throw Exceptions::InternalError( "Found a free angle in specialUnitService." );
89 CHECK(
90 if( IS_NAN( ag0 ) )
92 std::ostringstream msg;
93 msg << "Using uninitialized adjacent angle in "
94 << "(" << Concrete::Length::offtype( x0 ) << "bp," << Concrete::Length::offtype( y0 ) << "bp)"
95 << "--"
96 << "(" << Concrete::Length::offtype( x3 ) << "bp," << Concrete::Length::offtype( y3 ) << "bp)" ;
97 throw Exceptions::InternalError( strrefdup( msg ) );
101 double ar0 = aRef - ag0;
102 if( ar0 < - M_PI )
106 ar0 += 2 * M_PI;
108 while( ar0 < - M_PI );
110 else
112 while( ar0 > M_PI )
114 ar0 -= 2 * M_PI;
118 double ar1 = ag1 - aRef - M_PI;
119 if( IS_NAN( ag1 ) )
121 /* The angle is NaN is there is no opposite angle. The implicit direction is then towards the neighboring point.
123 ar1 = 0;
125 else
127 if( ar1 < - M_PI )
131 ar1 += 2 * M_PI;
133 while( ar1 < - M_PI );
135 else
137 while( ar1 > M_PI )
139 ar1 -= 2 * M_PI;
144 if( ar0 < 0 )
146 ar0 = - ar0;
147 ar1 = - ar1;
150 ar1 -= ar0;
152 if( ar1 < - M_PI )
154 ar1 += 2 * M_PI;
156 else if( ar1 > M_PI )
158 ar1 -= 2 * M_PI;
161 *a0 = ar0;
162 *a1 = ar1;
165 Kernel::SystemDynamicVariables::SystemDynamicVariables( )
166 : graphicsState_( NullPtr< const Kernel::GraphicsState >( ) ),
167 facetState_( NullPtr< const Kernel::FacetState >( ) ),
168 textState_( NullPtr< const Kernel::TextState >( ) ),
169 eyez_( std::numeric_limits< double >::signaling_NaN( ) ),
170 TeX_bleed_( std::numeric_limits< double >::signaling_NaN( ) ),
171 defaultUnit_( NullPtr< const Kernel::PolarHandlePromise >( ) ),
172 blendSpace_( NullPtr< const Lang::ColorSpace >( ) )
175 Kernel::SystemDynamicVariables::SystemDynamicVariables( const RefCountPtr< const Kernel::GraphicsState > & graphicsState )
176 : graphicsState_( graphicsState ),
177 facetState_( new Kernel::FacetState( true ) ),
178 textState_( new Kernel::TextState( true ) ),
179 eyez_( 50 * 72 / 2.54 ), /* 50 cm */
180 TeX_bleed_( 0.5 ), /* 0.5 bp */
181 defaultUnit_( new Kernel::PolarHandleEmptyPromise( ) ),
182 blendSpace_( Lang::THE_INHERITED_COLOR_SPACE )
185 void
186 Kernel::SystemDynamicVariables::addFrom( const SystemDynamicVariables & other )
188 if( graphicsState_ == NullPtr< const Kernel::GraphicsState >( ) )
190 graphicsState_ = other.graphicsState_;
192 else if( other.graphicsState_ != NullPtr< const Kernel::GraphicsState >( ) )
194 graphicsState_ = RefCountPtr< const Kernel::GraphicsState >( new Kernel::GraphicsState( *graphicsState_, *other.graphicsState_ ) );
196 /* In the remaining situation, there is nothing to merge, so we're done. */
198 if( facetState_ == NullPtr< const Kernel::FacetState >( ) )
200 facetState_ = other.facetState_;
202 else if( other.facetState_ != NullPtr< const Kernel::FacetState >( ) )
204 facetState_ = RefCountPtr< const Kernel::FacetState >( new Kernel::FacetState( *facetState_, *other.facetState_ ) );
206 /* In the remaining situation, there is nothing to merge, so we're done. */
208 if( textState_ == NullPtr< const Kernel::TextState >( ) )
210 textState_ = other.textState_;
212 else if( other.textState_ != NullPtr< const Kernel::TextState >( ) )
214 textState_ = RefCountPtr< const Kernel::TextState >( new Kernel::TextState( *textState_, *other.textState_ ) );
216 /* In the remaining situation, there is nothing to merge, so we're done. */
218 if( IS_NAN( eyez_ ) )
220 eyez_ = other.eyez_;
223 if( IS_NAN( TeX_bleed_ ) )
225 TeX_bleed_ = other.TeX_bleed_;
228 if( defaultUnit_ == NullPtr< const Kernel::PolarHandlePromise >( ) )
230 defaultUnit_ = other.defaultUnit_;
233 if( blendSpace_ == NullPtr< const Lang::ColorSpace >( ) )
235 blendSpace_ = other.blendSpace_;
239 void
240 Kernel::SystemDynamicVariables::print( std::ostream & os, const std::string & indentation ) const
242 const char * moreIndentation = " ";
244 if( graphicsState_ != NullPtr< const Kernel::GraphicsState >( ) )
246 os << indentation << "Graphics state bindings:" << std::endl ;
247 graphicsState_->print( os, indentation + moreIndentation );
250 if( textState_ != NullPtr< const Kernel::TextState >( ) )
252 os << indentation << "Text state bindings:" << std::endl ;
253 textState_->print( os, indentation + moreIndentation );
256 if( facetState_ != NullPtr< const Kernel::FacetState >( ) )
258 os << indentation << "Facet state bindings:" << std::endl ;
259 facetState_->print( os, indentation + moreIndentation );
262 if( ! IS_NAN( eyez_ ) )
264 os << indentation ;
265 Lang::DYNAMIC_VARIABLE_ID_EYEZ.show( os, Ast::Identifier::DYNAMIC_VARIABLE );
266 os << ": " << eyez_ / Interaction::displayUnit << Interaction::displayUnitName << std::endl ;
269 if( ! IS_NAN( TeX_bleed_ ) )
271 os << indentation ;
272 Lang::DYNAMIC_VARIABLE_ID_TEX_BLEED.show( os, Ast::Identifier::DYNAMIC_VARIABLE );
273 os << ": " << TeX_bleed_ / Interaction::displayUnit << Interaction::displayUnitName << std::endl ;
276 if( defaultUnit_ != NullPtr< const Kernel::PolarHandlePromise >( ) )
278 os << indentation ;
279 Lang::DYNAMIC_VARIABLE_ID_DEFAULT_UNIT.show( os, Ast::Identifier::DYNAMIC_VARIABLE );
280 os << ": " ;
281 defaultUnit_->show( os );
282 os << std::endl ;
285 if( blendSpace_ != NullPtr< const Lang::ColorSpace >( ) )
287 os << indentation ;
288 Lang::DYNAMIC_VARIABLE_ID_BLEND_SPACE.show( os, Ast::Identifier::DYNAMIC_VARIABLE );
289 os << ": " ;
290 if( blendSpace_->isInherent( ) )
292 os << "< inherent >" << std::endl ;
294 else
296 os << blendSpace_->name( ) << std::endl ;
303 Kernel::DynamicEnvironment::DynamicEnvironment( const RefCountPtr< const Kernel::GraphicsState > & graphicsState )
304 : parent_( NullPtr< Kernel::DynamicEnvironment >( ) ), sysBindings_( new Kernel::SystemDynamicVariables( graphicsState ) ),
305 specialBindings_( 0 ), spanLast_( 0 ),
306 contId_( Lang::CONTINUATION_ID_ERROR ), contVal_( Kernel::ContRef( new Kernel::DefaultErrorContinuation( Ast::theProgram->loc( ) ) ) )
309 Kernel::DynamicEnvironment::DynamicEnvironment( RefCountPtr< Kernel::DynamicEnvironment > parent, const Lang::DynamicBindings & bindings )
310 : parent_( NullPtr< Kernel::DynamicEnvironment >( ) ), sysBindings_( 0 ), specialBindings_( 0 ), spanLast_( 0 ),
311 contId_( 0 ), contVal_( NullPtr< Kernel::Continuation >( ) )
313 bindings.bind( bindings_, & sysBindings_ );
314 if( sysBindings_ != 0 &&
315 sysBindings_->graphicsState_ != NullPtr< const Kernel::GraphicsState >( ) )
317 sysBindings_->graphicsState_ =
318 RefCountPtr< const Kernel::GraphicsState >( new Kernel::GraphicsState( *(sysBindings_->graphicsState_),
319 *(parent->getGraphicsState( )) ) );
321 if( sysBindings_ != 0 &&
322 sysBindings_->facetState_ != NullPtr< const Kernel::FacetState >( ) )
324 sysBindings_->facetState_ =
325 RefCountPtr< const Kernel::FacetState >( new Kernel::FacetState( *(sysBindings_->facetState_),
326 *(parent->getFacetState( )) ) );
328 if( sysBindings_ != 0 &&
329 sysBindings_->textState_ != NullPtr< const Kernel::TextState >( ) )
331 sysBindings_->textState_ =
332 RefCountPtr< const Kernel::TextState >( new Kernel::TextState( *(sysBindings_->textState_),
333 *(parent->getTextState( )) ) );
335 parent_ = parent->selectParent( parent, bindings_ );
338 Kernel::DynamicEnvironment::DynamicEnvironment( RefCountPtr< Kernel::DynamicEnvironment > parent, const RefCountPtr< const Kernel::GraphicsState > & graphicsState )
339 : parent_( parent ), sysBindings_( new Kernel::SystemDynamicVariables( ) ), specialBindings_( 0 ), spanLast_( 0 ),
340 contId_( 0 ), contVal_( NullPtr< Kernel::Continuation >( ) )
342 sysBindings_->graphicsState_ = graphicsState;
345 Kernel::DynamicEnvironment::DynamicEnvironment( RefCountPtr< Kernel::DynamicEnvironment > parent, Kernel::SystemDynamicVariables * sysBindings )
346 : parent_( parent ), sysBindings_( sysBindings ), specialBindings_( 0 ), spanLast_( 0 ),
347 contId_( 0 ), contVal_( NullPtr< Kernel::Continuation >( ) )
350 Kernel::DynamicEnvironment::DynamicEnvironment( RefCountPtr< Kernel::DynamicEnvironment > parent, Kernel::SpecialUnitVariables * specialBindings )
351 : parent_( parent ), sysBindings_( 0 ), specialBindings_( specialBindings ), spanLast_( 0 ),
352 contId_( 0 ), contVal_( NullPtr< Kernel::Continuation >( ) )
355 Kernel::DynamicEnvironment::DynamicEnvironment( RefCountPtr< Kernel::DynamicEnvironment > parent, const RefCountPtr< const Lang::Value > & spanLast )
356 : parent_( parent ), sysBindings_( 0 ), specialBindings_( 0 ), spanLast_( new Kernel::SpanLastValue( spanLast ) ),
357 contId_( 0 ), contVal_( NullPtr< Kernel::Continuation >( ) )
361 Kernel::DynamicEnvironment::DynamicEnvironment( RefCountPtr< Kernel::DynamicEnvironment > parent, const char * contId, const Kernel::ContRef & contVal )
362 : parent_( parent ), sysBindings_( 0 ), specialBindings_( 0 ), spanLast_( 0 ),
363 contId_( contId ), contVal_( contVal )
366 Kernel::DynamicEnvironment::~DynamicEnvironment( )
368 if( sysBindings_ != 0 )
370 delete sysBindings_;
372 if( specialBindings_ != 0 )
374 delete specialBindings_;
376 if( spanLast_ != 0 )
378 delete spanLast_;
382 void
383 Kernel::DynamicEnvironment::tackOn( const KeyType & key, Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
385 throw Exceptions::NotImplemented( "DynamicEnvironment::tackOn" );
386 // MapType::iterator i = bindings_.find( key );
387 // if( i == bindings_.end( ) )
388 // {
389 // if( isBaseEnvironment( ) )
390 // {
391 // throw Exceptions::InternalError( "Key of dynamic variable was not found in dynamic environment." );
392 // }
393 // return parent_->tackOn( key, evalState, piece, callLoc );
394 // }
395 // return i->second.first->tackOn( evalState, piece, callLoc );
398 void
399 Kernel::DynamicEnvironment::lookup( const KeyType & key, Kernel::EvalState * evalState ) const
401 MapType::const_iterator i = bindings_.find( key );
402 if( i == bindings_.end( ) )
404 if( isBaseEnvironment( ) )
406 throw NonLocalExit::DynamicBindingNotFound( );
408 return parent_->lookup( key, evalState );
411 Kernel::ContRef cont = evalState->cont_;
412 cont->takeHandle( i->second.first,
413 evalState );
416 Kernel::VariableHandle
417 Kernel::DynamicEnvironment::getVarHandle( const KeyType & key ) const
419 MapType::const_iterator i = bindings_.find( key );
420 if( i == bindings_.end( ) )
422 if( isBaseEnvironment( ) )
424 throw NonLocalExit::DynamicBindingNotFound( );
426 return parent_->getVarHandle( key );
428 return i->second.first;
431 RefCountPtr< Kernel::DynamicEnvironment >
432 Kernel::DynamicEnvironment::selectParent( RefCountPtr< Kernel::DynamicEnvironment > & self, const MapType & newBindings )
434 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) ||
435 sysBindings_ != 0 ||
436 specialBindings_ != 0 ||
437 spanLast_ != 0 ||
438 contId_ != 0 )
440 return self;
443 MapType::const_iterator hint = newBindings.begin( );
444 for( MapType::const_iterator i = bindings_.begin( ); i != bindings_.end( ); ++i )
446 hint = newBindings.find( i->first );
447 if( hint == newBindings.end( ) )
449 return self;
453 return parent_->selectParent( parent_, newBindings );
456 void
457 Kernel::DynamicEnvironment::gcMark( Kernel::GCMarkedSet & marked )
459 for( MapType::iterator i = bindings_.begin( ); i != bindings_.end( ); ++i )
461 i->second.first->gcMark( marked );
466 RefCountPtr< const Kernel::GraphicsState >
467 Kernel::DynamicEnvironment::getGraphicsState( ) const
469 if( sysBindings_ == 0 ||
470 sysBindings_->graphicsState_ == NullPtr< const Kernel::GraphicsState >( ) )
472 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
474 throw Exceptions::InternalError( "The graphics state was needed but not defined." );
476 return parent_->getGraphicsState( );
479 return sysBindings_->graphicsState_;
482 RefCountPtr< const Kernel::FacetState >
483 Kernel::DynamicEnvironment::getFacetState( ) const
485 if( sysBindings_ == 0 ||
486 sysBindings_->facetState_ == NullPtr< const Kernel::FacetState >( ) )
488 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
490 throw Exceptions::InternalError( "The facet state was needed but not defined." );
492 return parent_->getFacetState( );
495 return sysBindings_->facetState_;
498 RefCountPtr< const Kernel::TextState >
499 Kernel::DynamicEnvironment::getTextState( ) const
501 if( sysBindings_ == 0 ||
502 sysBindings_->textState_ == NullPtr< const Kernel::TextState >( ) )
504 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
506 throw Exceptions::InternalError( "The text state was needed but not defined." );
508 return parent_->getTextState( );
511 return sysBindings_->textState_;
514 Concrete::Length
515 Kernel::DynamicEnvironment::getEyeZ( ) const
517 if( sysBindings_ == 0 ||
518 IS_NAN( sysBindings_->eyez_ ) )
520 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
522 throw Exceptions::InternalError( "@eyez should allways be bound." );
524 return parent_->getEyeZ( );
527 return sysBindings_->eyez_;
530 Concrete::Length
531 Kernel::DynamicEnvironment::getTeXBleed( ) const
533 if( sysBindings_ == 0 ||
534 IS_NAN( sysBindings_->TeX_bleed_ ) )
536 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
538 throw Exceptions::InternalError( "@TeX_bleed should allways be bound." );
540 return parent_->getTeXBleed( );
543 return sysBindings_->TeX_bleed_;
546 RefCountPtr< const Kernel::PolarHandlePromise >
547 Kernel::DynamicEnvironment::getDefaultUnit( ) const
549 if( sysBindings_ == 0 ||
550 sysBindings_->defaultUnit_ == NullPtr< const Kernel::PolarHandlePromise >( ) )
552 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
554 throw Exceptions::InternalError( "The default unit should allways be defined." );
556 return parent_->getDefaultUnit( );
559 return sysBindings_->defaultUnit_;
562 RefCountPtr< const Lang::Value >
563 Kernel::DynamicEnvironment::getSpanLast( ) const
565 if( spanLast_ == 0 )
567 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
569 throw Exceptions::InternalError( "The value of %last is not determined by the current dynamic context." );
571 return parent_->getSpanLast( );
574 return spanLast_->last_;
577 Kernel::ContRef
578 Kernel::DynamicEnvironment::getEscapeContinuation( const char * id, const Ast::SourceLocation & loc ) const
580 if( contId_ == 0 ||
581 strcmp( contId_, id ) != 0 )
583 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
585 throw Exceptions::UndefinedEscapeContinuation( id, loc );
587 return parent_->getEscapeContinuation( id, loc );
590 return contVal_;
593 RefCountPtr< const Lang::ColorSpace >
594 Kernel::DynamicEnvironment::getBlendSpace( ) const
596 if( sysBindings_ == 0 ||
597 sysBindings_->blendSpace_ == NullPtr< const Lang::ColorSpace >( ) )
599 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
601 throw Exceptions::InternalError( "The blend space should allways be defined." );
603 return parent_->getBlendSpace( );
606 return sysBindings_->blendSpace_;
609 void
610 Kernel::DynamicEnvironment::specialUnitService( Concrete::Length * d, double * a0, double * a1 )
612 if( specialBindings_ != 0 )
614 specialBindings_->specialUnitService( d, a0, a1 );
616 else
618 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
620 throw Exceptions::InternalError( "The special unit dynamic context was needed but not defined." );
622 parent_->specialUnitService( d, a0, a1 );
626 bool
627 Kernel::DynamicEnvironment::isBaseEnvironment( ) const
629 return parent_ == NullPtr< Kernel::DynamicEnvironment >( );
632 void
633 Kernel::DynamicEnvironment::print( std::ostream & os ) const
635 std::set< MapType::key_type > shadowed;
636 recursivePrint( os, & shadowed );
639 size_t
640 Kernel::DynamicEnvironment::recursivePrint( std::ostream & os, std::set< MapType::key_type > * shadowed ) const
642 std::set< MapType::key_type > shadowedBefore( *shadowed );
644 size_t depth = 0;
645 if( ! isBaseEnvironment( ) )
647 for( MapType::const_iterator i = bindings_.begin( ); i != bindings_.end( ); ++i )
649 shadowed->insert( shadowed->begin( ), i->first );
651 depth = parent_->recursivePrint( os, shadowed ) + 1;
654 std::string indentation = std::string( depth, ' ' );
656 os << indentation << "@@ -- -- -- -- -- -- -- -- @@" << std::endl ;
658 if( contId_ != 0 )
660 os << indentation << " (esc) " << "< escape continuation > " << contId_ << ": " << contVal_->traceLoc( ) << " (" << contVal_->description( ) << ")" << std::endl ;
663 if( sysBindings_ != 0 )
665 sysBindings_->print( os, indentation + " (sys) " ); /* The extra indentation matches " (num) " */
668 if( specialBindings_ != 0 )
670 os << indentation << " (-- ) " << "< special unit points >: " << *(specialBindings_->p0_->mid_) << ( (specialBindings_->reverseDirection_) ? " <-- " : " --> " ) << *(specialBindings_->p1_->mid_) << std::endl ;
673 if( spanLast_ != 0 )
675 os << indentation << " (spn) " << "< %last >: " ;
676 spanLast_->last_->show( os );
677 os << std::endl ;
680 for( MapType::const_iterator i = bindings_.begin( ); i != bindings_.end( ); ++i )
682 os << indentation ;
683 if( shadowedBefore.find( i->first ) != shadowedBefore.end( ) )
685 os << "#" ;
687 else
689 os << " " ;
691 os << "(" << std::setw(3) << i->first << ") " << Interaction::DYNAMIC_VARIABLE_PREFIX << i->second.second->id( ) << ": " ;
692 if( i->second.first == NullPtr< Kernel::Variable >( ) )
694 os << "< Uninitialized >" ;
696 else if( i->second.first->isThunk( ) )
698 os << "< thunk >" ;
700 else if( dynamic_cast< const Lang::Instance * >( i->second.first->getUntyped( ).getPtr( ) ) == 0 )
702 i->second.first->getUntyped( )->show( os );
704 else
706 os << "..." ;
708 os << " (" << i->second.second->idLoc( ) << ")" << std::endl ;
711 // os << indentation << "-- -- -- -- -- -- -- -- -- --" << std::endl ;
713 return depth;
716 Lang::EyeZBinding::EyeZBinding( const Ast::PlacedIdentifier * id, const Ast::DynamicBindingExpression * bindingExpr, Concrete::Length val )
717 : bindingExpr_( bindingExpr ), val_( val ), id_( id )
720 Lang::EyeZBinding::~EyeZBinding( )
723 void
724 Lang::EyeZBinding::bind( MapType & bindings, Kernel::SystemDynamicVariables ** sysBindings ) const
726 if( *sysBindings == 0 )
728 *sysBindings = new Kernel::SystemDynamicVariables( );
729 (*sysBindings)->eyez_ = val_;
730 return;
733 if( ! IS_NAN( (*sysBindings)->eyez_ ) )
735 throw Exceptions::MultipleDynamicBind( id_, bindingExpr_->idLoc( ), Ast::THE_UNKNOWN_LOCATION );
738 (*sysBindings)->eyez_ = val_;
741 void
742 Lang::EyeZBinding::show( std::ostream & os ) const
744 os << Interaction::DYNAMIC_VARIABLE_PREFIX << id_ << ":"
745 << val_ / Interaction::displayUnit << Interaction::displayUnitName ;
748 void
749 Lang::EyeZBinding::gcMark( Kernel::GCMarkedSet & marked )
754 Kernel::EyeZDynamicVariableProperties::EyeZDynamicVariableProperties( const Ast::PlacedIdentifier * id )
755 : Kernel::DynamicVariableProperties( id )
758 Kernel::EyeZDynamicVariableProperties::~EyeZDynamicVariableProperties( )
761 Kernel::VariableHandle
762 Kernel::EyeZDynamicVariableProperties::fetch( const Kernel::PassedDyn & dyn ) const
764 return Helpers::newValHandle( new Lang::Length( dyn->getEyeZ( ) ) );
767 void
768 Kernel::EyeZDynamicVariableProperties::makeBinding( Kernel::VariableHandle val, const Ast::DynamicBindingExpression * bindingExpr, Kernel::EvalState * evalState ) const
772 RefCountPtr< const Lang::Length > len = val->tryVal< const Lang::Length >( );
773 Kernel::ContRef cont = evalState->cont_;
774 cont->takeValue( Kernel::ValueRef( new Lang::EyeZBinding( id_, bindingExpr, len->get( ) ) ),
775 evalState );
776 return;
778 catch( const NonLocalExit::NotThisType & ball )
780 /* never mind */
785 RefCountPtr< const Lang::Float > maybeInfinity = val->tryVal< const Lang::Float >( );
786 if( maybeInfinity->val_ < HUGE_VAL )
788 throw Exceptions::OutOfRange( bindingExpr->exprLoc( ), strrefdup( "The only float value allowed here is infinity." ) );
790 Kernel::ContRef cont = evalState->cont_;
791 cont->takeValue( Kernel::ValueRef( new Lang::EyeZBinding( id_, bindingExpr, Concrete::HUGE_LENGTH ) ),
792 evalState );
793 return;
795 catch( const NonLocalExit::NotThisType & ball )
797 /* never mind */
800 throw Exceptions::TypeMismatch( bindingExpr->exprLoc( ), val->getUntyped( )->getTypeName( ), Helpers::typeSetString( Lang::Length::staticTypeName( ), Lang::Float::staticTypeName( ) ) );
804 Lang::DefaultUnitBinding::DefaultUnitBinding( const Ast::PlacedIdentifier * id, const Ast::DynamicBindingExpression * bindingExpr, const RefCountPtr< const Kernel::PolarHandlePromise > & val )
805 : bindingExpr_( bindingExpr ), val_( val ), id_( id )
808 Lang::DefaultUnitBinding::~DefaultUnitBinding( )
811 void
812 Lang::DefaultUnitBinding::bind( MapType & bindings, Kernel::SystemDynamicVariables ** sysBindings ) const
814 if( *sysBindings == 0 )
816 *sysBindings = new Kernel::SystemDynamicVariables( );
817 (*sysBindings)->defaultUnit_ = val_;
818 return;
821 if( (*sysBindings)->defaultUnit_ != NullPtr< const Kernel::PolarHandlePromise >( ) )
823 throw Exceptions::MultipleDynamicBind( id_, bindingExpr_->idLoc( ), Ast::THE_UNKNOWN_LOCATION );
826 (*sysBindings)->defaultUnit_ = val_;
829 void
830 Lang::DefaultUnitBinding::show( std::ostream & os ) const
832 os << Interaction::DYNAMIC_VARIABLE_PREFIX << id_ << ":<promise>" ;
835 void
836 Lang::DefaultUnitBinding::gcMark( Kernel::GCMarkedSet & marked )
838 val_->gcMark( marked );
842 Kernel::DefaultUnitDynamicVariableProperties::DefaultUnitDynamicVariableProperties( const Ast::PlacedIdentifier * id )
843 : Kernel::DynamicVariableProperties( id )
846 Kernel::DefaultUnitDynamicVariableProperties::~DefaultUnitDynamicVariableProperties( )
849 Kernel::VariableHandle
850 Kernel::DefaultUnitDynamicVariableProperties::fetch( const Kernel::PassedDyn & dyn ) const
852 throw Exceptions::MiscellaneousRequirement( "The default unit cannot be evaluated as a variable." );
855 void
856 Kernel::DefaultUnitDynamicVariableProperties::makeBinding( Kernel::VariableHandle val, const Ast::DynamicBindingExpression * bindingExpr, Kernel::EvalState * evalState ) const
858 if( ! val->isThunk( ) )
860 throw Exceptions::InternalError( "The default unit handle was not a thunk." );
863 Kernel::ContRef cont = evalState->cont_;
864 cont->takeValue( Kernel::ValueRef( new Lang::DefaultUnitBinding( id_, bindingExpr, RefCountPtr< const Kernel::PolarHandlePromise >( new Kernel::PolarHandleTruePromise( val->copyThunk( ) ) ) ) ),
865 evalState );
866 return;
870 Lang::TeXBleedBinding::TeXBleedBinding( const Ast::PlacedIdentifier * id, const Ast::DynamicBindingExpression * bindingExpr, Concrete::Length val )
871 : bindingExpr_( bindingExpr ), val_( val ), id_( id )
874 Lang::TeXBleedBinding::~TeXBleedBinding( )
877 void
878 Lang::TeXBleedBinding::bind( MapType & bindings, Kernel::SystemDynamicVariables ** sysBindings ) const
880 if( *sysBindings == 0 )
882 *sysBindings = new Kernel::SystemDynamicVariables( );
883 (*sysBindings)->TeX_bleed_ = val_;
884 return;
887 if( ! IS_NAN( (*sysBindings)->TeX_bleed_ ) )
889 throw Exceptions::MultipleDynamicBind( id_, bindingExpr_->idLoc( ), Ast::THE_UNKNOWN_LOCATION );
892 (*sysBindings)->TeX_bleed_ = val_;
895 void
896 Lang::TeXBleedBinding::show( std::ostream & os ) const
898 os << Interaction::DYNAMIC_VARIABLE_PREFIX << id_ << ":"
899 << val_ / Interaction::displayUnit << Interaction::displayUnitName ;
902 void
903 Lang::TeXBleedBinding::gcMark( Kernel::GCMarkedSet & marked )
908 Kernel::TeXBleedDynamicVariableProperties::TeXBleedDynamicVariableProperties( const Ast::PlacedIdentifier * id )
909 : Kernel::DynamicVariableProperties( id )
912 Kernel::TeXBleedDynamicVariableProperties::~TeXBleedDynamicVariableProperties( )
915 Kernel::VariableHandle
916 Kernel::TeXBleedDynamicVariableProperties::fetch( const Kernel::PassedDyn & dyn ) const
918 return Helpers::newValHandle( new Lang::Length( dyn->getTeXBleed( ) ) );
921 void
922 Kernel::TeXBleedDynamicVariableProperties::makeBinding( Kernel::VariableHandle val, const Ast::DynamicBindingExpression * bindingExpr, Kernel::EvalState * evalState ) const
924 RefCountPtr< const Lang::Length > len = val->getVal< const Lang::Length >( bindingExpr->exprLoc( ) );
925 Kernel::ContRef cont = evalState->cont_;
926 cont->takeValue( Kernel::ValueRef( new Lang::TeXBleedBinding( id_, bindingExpr, len->get( ) ) ),
927 evalState );
931 Lang::BlendSpaceBinding::BlendSpaceBinding( const Ast::PlacedIdentifier * id, const Ast::DynamicBindingExpression * bindingExpr, const RefCountPtr< const Lang::ColorSpace > & space )
932 : bindingExpr_( bindingExpr ), space_( space ), id_( id )
935 Lang::BlendSpaceBinding::~BlendSpaceBinding( )
938 void
939 Lang::BlendSpaceBinding::bind( MapType & bindings, Kernel::SystemDynamicVariables ** sysBindings ) const
941 if( *sysBindings == 0 )
943 *sysBindings = new Kernel::SystemDynamicVariables( );
944 (*sysBindings)->blendSpace_ = space_;
945 return;
948 if( (*sysBindings)->blendSpace_ != NullPtr< const Lang::ColorSpace >( ) )
950 throw Exceptions::MultipleDynamicBind( id_, bindingExpr_->idLoc( ), Ast::THE_UNKNOWN_LOCATION );
953 (*sysBindings)->blendSpace_ = space_;
956 void
957 Lang::BlendSpaceBinding::show( std::ostream & os ) const
959 os << Interaction::DYNAMIC_VARIABLE_PREFIX << id_ << "" ;
960 space_->show( os );
963 void
964 Lang::BlendSpaceBinding::gcMark( Kernel::GCMarkedSet & marked )
969 Kernel::BlendSpaceDynamicVariableProperties::BlendSpaceDynamicVariableProperties( const Ast::PlacedIdentifier * id )
970 : Kernel::DynamicVariableProperties( id )
973 Kernel::BlendSpaceDynamicVariableProperties::~BlendSpaceDynamicVariableProperties( )
976 Kernel::VariableHandle
977 Kernel::BlendSpaceDynamicVariableProperties::fetch( const Kernel::PassedDyn & dyn ) const
979 return Kernel::VariableHandle( new Kernel::Variable( dyn->getBlendSpace( ) ) );
982 void
983 Kernel::BlendSpaceDynamicVariableProperties::makeBinding( Kernel::VariableHandle val, const Ast::DynamicBindingExpression * bindingExpr, Kernel::EvalState * evalState ) const
985 RefCountPtr< const Lang::ColorSpace > space = val->getVal< const Lang::ColorSpace >( bindingExpr->exprLoc( ) );
986 if( ! space->isBlendable( ) )
988 throw Exceptions::OutOfRange( bindingExpr->exprLoc( ), strrefdup( "This color space cannot be used in blending." ) );
991 Kernel::ContRef cont = evalState->cont_;
992 cont->takeValue( Kernel::ValueRef( new Lang::BlendSpaceBinding( id_, bindingExpr, space ) ),
993 evalState );
997 Kernel::SpotDynamicVariableProperties::SpotDynamicVariableProperties( const Ast::PlacedIdentifier * id )
998 : Kernel::DynamicVariableProperties( id )
1001 Kernel::SpotDynamicVariableProperties::~SpotDynamicVariableProperties( )
1004 Kernel::VariableHandle
1005 Kernel::SpotDynamicVariableProperties::fetch( const Kernel::PassedDyn & dyn ) const
1007 /* Note that this code should be very similar to Core_spot::call.
1010 static RefCountPtr< const Lang::ElementaryPath2D > pth = RefCountPtr< const Lang::ElementaryPath2D >( NullPtr< const Lang::ElementaryPath2D >( ) );
1011 if( pth == NullPtr< const Lang::ElementaryPath2D >( ) )
1013 Lang::ElementaryPath2D * mem = new Lang::ElementaryPath2D;
1014 mem->push_back( new Concrete::PathPoint2D( Concrete::ZERO_LENGTH, Concrete::ZERO_LENGTH ) );
1015 if( Kernel::allowSingletonPaths )
1017 mem->close( );
1019 else
1021 mem->push_back( new Concrete::PathPoint2D( Concrete::ZERO_LENGTH, Concrete::ZERO_LENGTH ) );
1023 pth = RefCountPtr< const Lang::ElementaryPath2D >( mem );
1026 Kernel::GraphicsState * capState( new Kernel::GraphicsState( *dyn->getGraphicsState( ) ) );
1027 capState->cap_ = Lang::CapStyle::CAP_ROUND;
1029 return Helpers::newValHandle( new Lang::PaintedPath2D
1030 ( RefCountPtr< const Kernel::GraphicsState >( capState ),
1031 pth,
1032 "S" ) );
1035 void
1036 Kernel::SpotDynamicVariableProperties::makeBinding( Kernel::VariableHandle val, const Ast::DynamicBindingExpression * bindingExpr, Kernel::EvalState * evalState ) const
1038 std::ostringstream msg;
1039 msg << "The dynamic variable " ;
1040 id_->show( msg, Ast::Identifier::DYNAMIC_VARIABLE );
1041 msg << " cannot be changed from its default." ;
1042 throw Exceptions::MiscellaneousRequirement( strrefdup( msg ) );
1046 Kernel::DynamicEnvironment::KeyType Kernel::DynamicEnvironment::nextKey( 0 );
1048 Kernel::DynamicEnvironment::KeyType
1049 Kernel::DynamicEnvironment::getFreshKey( )
1051 ++nextKey;
1052 return nextKey;
1057 Lang::DynamicExpression::DynamicExpression( Kernel::PassedEnv env, Ast::Expression * expr )
1058 : env_( env ), expr_( expr )
1061 Lang::DynamicExpression::~DynamicExpression( )
1064 RefCountPtr< const Lang::Class > Lang::DynamicExpression::TypeID( new Lang::SystemFinalClass( strrefdup( "DynamicExpression" ) ) );
1065 TYPEINFOIMPL( DynamicExpression );
1067 void
1068 Lang::DynamicExpression::evalHelper( Kernel::EvalState * evalState ) const
1070 evalState->env_ = env_;
1071 evalState->expr_ = expr_;
1074 void
1075 Lang::DynamicExpression::gcMark( Kernel::GCMarkedSet & marked )
1077 env_->gcMark( marked );
1081 void
1082 Kernel::registerDynamic( Kernel::Environment * env )
1084 env->initDefineDynamic( new Kernel::WidthDynamicVariableProperties( & Lang::DYNAMIC_VARIABLE_ID_WIDTH ) );
1085 env->initDefineDynamic( new Kernel::CapStyleDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Traits, "cap" ) ) );
1086 env->initDefineDynamic( new Kernel::JoinStyleDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Traits, "join" ) ) );
1087 env->initDefineDynamic( new Kernel::MiterLimitDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Traits, "miterlimit" ) ) );
1088 env->initDefineDynamic( new Kernel::StrokingDynamicVariableProperties( & Lang::DYNAMIC_VARIABLE_ID_STROKING ) );
1089 env->initDefineDynamic( new Kernel::NonStrokingDynamicVariableProperties( & Lang::DYNAMIC_VARIABLE_ID_NONSTROKING ) );
1090 env->initDefineDynamic( new Kernel::DashDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Traits, "dash" ) ) );
1091 env->initDefineDynamic( new Kernel::BlendModeDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Traits, "blend" ) ) );
1092 env->initDefineDynamic( new Kernel::AlphaDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Traits, "nonstrokingalpha" ), false ) );
1093 env->initDefineDynamic( new Kernel::AlphaDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Traits, "strokingalpha" ), true ) );
1095 env->initDefineDynamic( new Kernel::ReflectionsDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Traits_Light, "reflections" ) ) );
1096 env->initDefineDynamic( new Kernel::AutoIntensityDynamicVariableProperties( & Lang::DYNAMIC_VARIABLE_ID_AUTOINTENSITY ) );
1097 env->initDefineDynamic( new Kernel::AutoScatteringDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Traits_Light, "autoscattering" ) ) );
1098 env->initDefineDynamic( new Kernel::ViewResolutionDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Traits_Light, "facetresolution" ) ) );
1099 env->initDefineDynamic( new Kernel::ShadeOrderDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Traits_Light, "shadeorder" ) ) );
1101 env->initDefineDynamic( new Kernel::CharacterSpacingDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Text, "characterspacing" ) ) );
1102 env->initDefineDynamic( new Kernel::WordSpacingDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Text, "wordspacing" ) ) );
1103 env->initDefineDynamic( new Kernel::HorizontalScalingDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Text, "horizontalscaling" ) ) );
1104 env->initDefineDynamic( new Kernel::LeadingDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Text, "leading" ) ) );
1105 env->initDefineDynamic( new Kernel::FontDynamicVariableProperties( & Lang::DYNAMIC_VARIABLE_ID_TEXT_FONT ) );
1106 env->initDefineDynamic( new Kernel::TextSizeDynamicVariableProperties( & Lang::DYNAMIC_VARIABLE_ID_TEXT_SIZE ) );
1107 env->initDefineDynamic( new Kernel::TextRenderingModeDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Text, "rendering" ) ) );
1108 env->initDefineDynamic( new Kernel::TextRiseDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Text, "rise" ) ) );
1109 env->initDefineDynamic( new Kernel::TextKnockoutDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Text, "knockout" ) ) );
1111 env->initDefineDynamic( new Kernel::TeXBleedDynamicVariableProperties( & Lang::DYNAMIC_VARIABLE_ID_TEX_BLEED ) );
1113 env->initDefineDynamic( new Kernel::EyeZDynamicVariableProperties( & Lang::DYNAMIC_VARIABLE_ID_EYEZ ) );
1114 env->initDefineDynamic( new Kernel::DefaultUnitDynamicVariableProperties( & Lang::DYNAMIC_VARIABLE_ID_DEFAULT_UNIT ) );
1115 env->initDefineDynamic( new Kernel::BlendSpaceDynamicVariableProperties( & Lang::DYNAMIC_VARIABLE_ID_BLEND_SPACE ) );
1117 env->initDefineDynamic( new Kernel::SpotDynamicVariableProperties( Kernel::Environment::newPlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Graphics, "spot" ) ) );