Example: Changed glyph-outline.shape for use with FontConfig.
[shapes.git] / source / dynamicenvironment.cc
blobaec3e762348d4a02aa0a9d997447b65ba15aaec1
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 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 << Interaction::DYNAMIC_VARIABLE_PREFIX << Lang::DYNAMIC_VARIABLE_ID_EYEZ << ": " << eyez_ / Interaction::displayUnit << Interaction::displayUnitName << std::endl ;
267 if( ! IS_NAN( TeX_bleed_ ) )
269 os << indentation << Interaction::DYNAMIC_VARIABLE_PREFIX << Lang::DYNAMIC_VARIABLE_ID_TEX_BLEED << ": " << TeX_bleed_ / Interaction::displayUnit << Interaction::displayUnitName << std::endl ;
272 if( defaultUnit_ != NullPtr< const Kernel::PolarHandlePromise >( ) )
274 os << indentation << Interaction::DYNAMIC_VARIABLE_PREFIX << Lang::DYNAMIC_VARIABLE_ID_DEFAULT_UNIT << ": " ;
275 defaultUnit_->show( os );
276 os << std::endl ;
279 if( blendSpace_ != NullPtr< const Lang::ColorSpace >( ) )
281 os << indentation << Interaction::DYNAMIC_VARIABLE_PREFIX << Lang::DYNAMIC_VARIABLE_ID_BLEND_SPACE << ": " ;
282 if( blendSpace_->isInherent( ) )
284 os << "< inherent >" << std::endl ;
286 else
288 os << blendSpace_->name( ) << std::endl ;
295 Kernel::DynamicEnvironment::DynamicEnvironment( const RefCountPtr< const Kernel::GraphicsState > & graphicsState )
296 : parent_( NullPtr< Kernel::DynamicEnvironment >( ) ), sysBindings_( new Kernel::SystemDynamicVariables( graphicsState ) ),
297 specialBindings_( 0 ), spanLast_( 0 ),
298 contId_( Lang::CONTINUATION_ID_ERROR ), contVal_( Kernel::ContRef( new Kernel::DefaultErrorContinuation( Ast::theProgram->loc( ) ) ) )
301 Kernel::DynamicEnvironment::DynamicEnvironment( RefCountPtr< Kernel::DynamicEnvironment > parent, const Lang::DynamicBindings & bindings )
302 : parent_( NullPtr< Kernel::DynamicEnvironment >( ) ), sysBindings_( 0 ), specialBindings_( 0 ), spanLast_( 0 ),
303 contId_( 0 ), contVal_( NullPtr< Kernel::Continuation >( ) )
305 bindings.bind( bindings_, & sysBindings_ );
306 if( sysBindings_ != 0 &&
307 sysBindings_->graphicsState_ != NullPtr< const Kernel::GraphicsState >( ) )
309 sysBindings_->graphicsState_ =
310 RefCountPtr< const Kernel::GraphicsState >( new Kernel::GraphicsState( *(sysBindings_->graphicsState_),
311 *(parent->getGraphicsState( )) ) );
313 if( sysBindings_ != 0 &&
314 sysBindings_->facetState_ != NullPtr< const Kernel::FacetState >( ) )
316 sysBindings_->facetState_ =
317 RefCountPtr< const Kernel::FacetState >( new Kernel::FacetState( *(sysBindings_->facetState_),
318 *(parent->getFacetState( )) ) );
320 if( sysBindings_ != 0 &&
321 sysBindings_->textState_ != NullPtr< const Kernel::TextState >( ) )
323 sysBindings_->textState_ =
324 RefCountPtr< const Kernel::TextState >( new Kernel::TextState( *(sysBindings_->textState_),
325 *(parent->getTextState( )) ) );
327 parent_ = parent->selectParent( parent, bindings_ );
330 Kernel::DynamicEnvironment::DynamicEnvironment( RefCountPtr< Kernel::DynamicEnvironment > parent, const RefCountPtr< const Kernel::GraphicsState > & graphicsState )
331 : parent_( parent ), sysBindings_( new Kernel::SystemDynamicVariables( ) ), specialBindings_( 0 ), spanLast_( 0 ),
332 contId_( 0 ), contVal_( NullPtr< Kernel::Continuation >( ) )
334 sysBindings_->graphicsState_ = graphicsState;
337 Kernel::DynamicEnvironment::DynamicEnvironment( RefCountPtr< Kernel::DynamicEnvironment > parent, Kernel::SystemDynamicVariables * sysBindings )
338 : parent_( parent ), sysBindings_( sysBindings ), specialBindings_( 0 ), spanLast_( 0 ),
339 contId_( 0 ), contVal_( NullPtr< Kernel::Continuation >( ) )
342 Kernel::DynamicEnvironment::DynamicEnvironment( RefCountPtr< Kernel::DynamicEnvironment > parent, Kernel::SpecialUnitVariables * specialBindings )
343 : parent_( parent ), sysBindings_( 0 ), specialBindings_( specialBindings ), spanLast_( 0 ),
344 contId_( 0 ), contVal_( NullPtr< Kernel::Continuation >( ) )
347 Kernel::DynamicEnvironment::DynamicEnvironment( RefCountPtr< Kernel::DynamicEnvironment > parent, const RefCountPtr< const Lang::Value > & spanLast )
348 : parent_( parent ), sysBindings_( 0 ), specialBindings_( 0 ), spanLast_( new Kernel::SpanLastValue( spanLast ) ),
349 contId_( 0 ), contVal_( NullPtr< Kernel::Continuation >( ) )
353 Kernel::DynamicEnvironment::DynamicEnvironment( RefCountPtr< Kernel::DynamicEnvironment > parent, const char * contId, const Kernel::ContRef & contVal )
354 : parent_( parent ), sysBindings_( 0 ), specialBindings_( 0 ), spanLast_( 0 ),
355 contId_( contId ), contVal_( contVal )
358 Kernel::DynamicEnvironment::~DynamicEnvironment( )
360 if( sysBindings_ != 0 )
362 delete sysBindings_;
364 if( specialBindings_ != 0 )
366 delete specialBindings_;
368 if( spanLast_ != 0 )
370 delete spanLast_;
374 void
375 Kernel::DynamicEnvironment::tackOn( const KeyType & key, Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
377 throw Exceptions::NotImplemented( "DynamicEnvironment::tackOn" );
378 // MapType::iterator i = bindings_.find( key );
379 // if( i == bindings_.end( ) )
380 // {
381 // if( isBaseEnvironment( ) )
382 // {
383 // throw Exceptions::InternalError( "Key of dynamic variable was not found in dynamic environment." );
384 // }
385 // return parent_->tackOn( key, evalState, piece, callLoc );
386 // }
387 // return i->second.first->tackOn( evalState, piece, callLoc );
390 void
391 Kernel::DynamicEnvironment::lookup( const KeyType & key, Kernel::EvalState * evalState ) const
393 MapType::const_iterator i = bindings_.find( key );
394 if( i == bindings_.end( ) )
396 if( isBaseEnvironment( ) )
398 throw NonLocalExit::DynamicBindingNotFound( );
400 return parent_->lookup( key, evalState );
403 Kernel::ContRef cont = evalState->cont_;
404 cont->takeHandle( i->second.first,
405 evalState );
408 Kernel::VariableHandle
409 Kernel::DynamicEnvironment::getVarHandle( const KeyType & key ) const
411 MapType::const_iterator i = bindings_.find( key );
412 if( i == bindings_.end( ) )
414 if( isBaseEnvironment( ) )
416 throw NonLocalExit::DynamicBindingNotFound( );
418 return parent_->getVarHandle( key );
420 return i->second.first;
423 RefCountPtr< Kernel::DynamicEnvironment >
424 Kernel::DynamicEnvironment::selectParent( RefCountPtr< Kernel::DynamicEnvironment > & self, const MapType & newBindings )
426 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) ||
427 sysBindings_ != 0 ||
428 specialBindings_ != 0 ||
429 spanLast_ != 0 ||
430 contId_ != 0 )
432 return self;
435 MapType::const_iterator hint = newBindings.begin( );
436 for( MapType::const_iterator i = bindings_.begin( ); i != bindings_.end( ); ++i )
438 hint = newBindings.find( i->first );
439 if( hint == newBindings.end( ) )
441 return self;
445 return parent_->selectParent( parent_, newBindings );
448 void
449 Kernel::DynamicEnvironment::gcMark( Kernel::GCMarkedSet & marked )
451 for( MapType::iterator i = bindings_.begin( ); i != bindings_.end( ); ++i )
453 i->second.first->gcMark( marked );
458 RefCountPtr< const Kernel::GraphicsState >
459 Kernel::DynamicEnvironment::getGraphicsState( ) const
461 if( sysBindings_ == 0 ||
462 sysBindings_->graphicsState_ == NullPtr< const Kernel::GraphicsState >( ) )
464 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
466 throw Exceptions::InternalError( "The graphics state was needed but not defined." );
468 return parent_->getGraphicsState( );
471 return sysBindings_->graphicsState_;
474 RefCountPtr< const Kernel::FacetState >
475 Kernel::DynamicEnvironment::getFacetState( ) const
477 if( sysBindings_ == 0 ||
478 sysBindings_->facetState_ == NullPtr< const Kernel::FacetState >( ) )
480 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
482 throw Exceptions::InternalError( "The facet state was needed but not defined." );
484 return parent_->getFacetState( );
487 return sysBindings_->facetState_;
490 RefCountPtr< const Kernel::TextState >
491 Kernel::DynamicEnvironment::getTextState( ) const
493 if( sysBindings_ == 0 ||
494 sysBindings_->textState_ == NullPtr< const Kernel::TextState >( ) )
496 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
498 throw Exceptions::InternalError( "The text state was needed but not defined." );
500 return parent_->getTextState( );
503 return sysBindings_->textState_;
506 Concrete::Length
507 Kernel::DynamicEnvironment::getEyeZ( ) const
509 if( sysBindings_ == 0 ||
510 IS_NAN( sysBindings_->eyez_ ) )
512 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
514 throw Exceptions::InternalError( "@eyez should allways be bound." );
516 return parent_->getEyeZ( );
519 return sysBindings_->eyez_;
522 Concrete::Length
523 Kernel::DynamicEnvironment::getTeXBleed( ) const
525 if( sysBindings_ == 0 ||
526 IS_NAN( sysBindings_->TeX_bleed_ ) )
528 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
530 throw Exceptions::InternalError( "@TeX_bleed should allways be bound." );
532 return parent_->getTeXBleed( );
535 return sysBindings_->TeX_bleed_;
538 RefCountPtr< const Kernel::PolarHandlePromise >
539 Kernel::DynamicEnvironment::getDefaultUnit( ) const
541 if( sysBindings_ == 0 ||
542 sysBindings_->defaultUnit_ == NullPtr< const Kernel::PolarHandlePromise >( ) )
544 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
546 throw Exceptions::InternalError( "The default unit should allways be defined." );
548 return parent_->getDefaultUnit( );
551 return sysBindings_->defaultUnit_;
554 RefCountPtr< const Lang::Value >
555 Kernel::DynamicEnvironment::getSpanLast( ) const
557 if( spanLast_ == 0 )
559 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
561 throw Exceptions::InternalError( "The value of %last is not determined by the current dynamic context." );
563 return parent_->getSpanLast( );
566 return spanLast_->last_;
569 Kernel::ContRef
570 Kernel::DynamicEnvironment::getEscapeContinuation( const char * id, const Ast::SourceLocation & loc ) const
572 if( contId_ == 0 ||
573 strcmp( contId_, id ) != 0 )
575 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
577 throw Exceptions::UndefinedEscapeContinuation( id, loc );
579 return parent_->getEscapeContinuation( id, loc );
582 return contVal_;
585 RefCountPtr< const Lang::ColorSpace >
586 Kernel::DynamicEnvironment::getBlendSpace( ) const
588 if( sysBindings_ == 0 ||
589 sysBindings_->blendSpace_ == NullPtr< const Lang::ColorSpace >( ) )
591 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
593 throw Exceptions::InternalError( "The blend space should allways be defined." );
595 return parent_->getBlendSpace( );
598 return sysBindings_->blendSpace_;
601 void
602 Kernel::DynamicEnvironment::specialUnitService( Concrete::Length * d, double * a0, double * a1 )
604 if( specialBindings_ != 0 )
606 specialBindings_->specialUnitService( d, a0, a1 );
608 else
610 if( parent_ == NullPtr< Kernel::DynamicEnvironment >( ) )
612 throw Exceptions::InternalError( "The special unit dynamic context was needed but not defined." );
614 parent_->specialUnitService( d, a0, a1 );
618 bool
619 Kernel::DynamicEnvironment::isBaseEnvironment( ) const
621 return parent_ == NullPtr< Kernel::DynamicEnvironment >( );
624 void
625 Kernel::DynamicEnvironment::print( std::ostream & os ) const
627 std::set< MapType::key_type > shadowed;
628 recursivePrint( os, & shadowed );
631 size_t
632 Kernel::DynamicEnvironment::recursivePrint( std::ostream & os, std::set< MapType::key_type > * shadowed ) const
634 std::set< MapType::key_type > shadowedBefore( *shadowed );
636 size_t depth = 0;
637 if( ! isBaseEnvironment( ) )
639 for( MapType::const_iterator i = bindings_.begin( ); i != bindings_.end( ); ++i )
641 shadowed->insert( shadowed->begin( ), i->first );
643 depth = parent_->recursivePrint( os, shadowed ) + 1;
646 std::string indentation = std::string( depth, ' ' );
648 os << indentation << "@@ -- -- -- -- -- -- -- -- @@" << std::endl ;
650 if( contId_ != 0 )
652 os << indentation << " (esc) " << "< escape continuation > " << contId_ << ": " << contVal_->traceLoc( ) << " (" << contVal_->description( ) << ")" << std::endl ;
655 if( sysBindings_ != 0 )
657 sysBindings_->print( os, indentation + " (sys) " ); /* The extra indentation matches " (num) " */
660 if( specialBindings_ != 0 )
662 os << indentation << " (-- ) " << "< special unit points >: " << *(specialBindings_->p0_->mid_) << ( (specialBindings_->reverseDirection_) ? " <-- " : " --> " ) << *(specialBindings_->p1_->mid_) << std::endl ;
665 if( spanLast_ != 0 )
667 os << indentation << " (spn) " << "< %last >: " ;
668 spanLast_->last_->show( os );
669 os << std::endl ;
672 for( MapType::const_iterator i = bindings_.begin( ); i != bindings_.end( ); ++i )
674 os << indentation ;
675 if( shadowedBefore.find( i->first ) != shadowedBefore.end( ) )
677 os << "#" ;
679 else
681 os << " " ;
683 os << "(" << std::setw(3) << i->first << ") " << Interaction::DYNAMIC_VARIABLE_PREFIX << i->second.second->id( ) << ": " ;
684 if( i->second.first == NullPtr< Kernel::Variable >( ) )
686 os << "< Uninitialized >" ;
688 else if( i->second.first->isThunk( ) )
690 os << "< thunk >" ;
692 else if( dynamic_cast< const Lang::Instance * >( i->second.first->getUntyped( ).getPtr( ) ) == 0 )
694 i->second.first->getUntyped( )->show( os );
696 else
698 os << "..." ;
700 os << " (" << i->second.second->idLoc( ) << ")" << std::endl ;
703 // os << indentation << "-- -- -- -- -- -- -- -- -- --" << std::endl ;
705 return depth;
708 Lang::EyeZBinding::EyeZBinding( const char * id, const Ast::DynamicBindingExpression * bindingExpr, Concrete::Length val )
709 : bindingExpr_( bindingExpr ), val_( val ), id_( id )
712 Lang::EyeZBinding::~EyeZBinding( )
715 void
716 Lang::EyeZBinding::bind( MapType & bindings, Kernel::SystemDynamicVariables ** sysBindings ) const
718 if( *sysBindings == 0 )
720 *sysBindings = new Kernel::SystemDynamicVariables( );
721 (*sysBindings)->eyez_ = val_;
722 return;
725 if( ! IS_NAN( (*sysBindings)->eyez_ ) )
727 throw Exceptions::MultipleDynamicBind( id_, bindingExpr_->idLoc( ), Ast::THE_UNKNOWN_LOCATION );
730 (*sysBindings)->eyez_ = val_;
733 void
734 Lang::EyeZBinding::show( std::ostream & os ) const
736 os << Interaction::DYNAMIC_VARIABLE_PREFIX << id_ << ":"
737 << val_ / Interaction::displayUnit << Interaction::displayUnitName ;
740 void
741 Lang::EyeZBinding::gcMark( Kernel::GCMarkedSet & marked )
746 Kernel::EyeZDynamicVariableProperties::EyeZDynamicVariableProperties( const char * _name )
747 : Kernel::DynamicVariableProperties( _name )
750 Kernel::EyeZDynamicVariableProperties::~EyeZDynamicVariableProperties( )
753 Kernel::VariableHandle
754 Kernel::EyeZDynamicVariableProperties::fetch( const Kernel::PassedDyn & dyn ) const
756 return Helpers::newValHandle( new Lang::Length( dyn->getEyeZ( ) ) );
759 void
760 Kernel::EyeZDynamicVariableProperties::makeBinding( Kernel::VariableHandle val, const Ast::DynamicBindingExpression * bindingExpr, Kernel::EvalState * evalState ) const
764 RefCountPtr< const Lang::Length > len = val->tryVal< const Lang::Length >( );
765 Kernel::ContRef cont = evalState->cont_;
766 cont->takeValue( Kernel::ValueRef( new Lang::EyeZBinding( name_, bindingExpr, len->get( ) ) ),
767 evalState );
768 return;
770 catch( const NonLocalExit::NotThisType & ball )
772 /* never mind */
777 RefCountPtr< const Lang::Float > maybeInfinity = val->tryVal< const Lang::Float >( );
778 if( maybeInfinity->val_ < HUGE_VAL )
780 throw Exceptions::OutOfRange( bindingExpr->exprLoc( ), strrefdup( "The only float value allowed here is infinity." ) );
782 Kernel::ContRef cont = evalState->cont_;
783 cont->takeValue( Kernel::ValueRef( new Lang::EyeZBinding( name_, bindingExpr, Concrete::HUGE_LENGTH ) ),
784 evalState );
785 return;
787 catch( const NonLocalExit::NotThisType & ball )
789 /* never mind */
792 throw Exceptions::TypeMismatch( bindingExpr->exprLoc( ), val->getUntyped( )->getTypeName( ), Helpers::typeSetString( Lang::Length::staticTypeName( ), Lang::Float::staticTypeName( ) ) );
796 Lang::DefaultUnitBinding::DefaultUnitBinding( const char * id, const Ast::DynamicBindingExpression * bindingExpr, const RefCountPtr< const Kernel::PolarHandlePromise > & val )
797 : bindingExpr_( bindingExpr ), val_( val ), id_( id )
800 Lang::DefaultUnitBinding::~DefaultUnitBinding( )
803 void
804 Lang::DefaultUnitBinding::bind( MapType & bindings, Kernel::SystemDynamicVariables ** sysBindings ) const
806 if( *sysBindings == 0 )
808 *sysBindings = new Kernel::SystemDynamicVariables( );
809 (*sysBindings)->defaultUnit_ = val_;
810 return;
813 if( (*sysBindings)->defaultUnit_ != NullPtr< const Kernel::PolarHandlePromise >( ) )
815 throw Exceptions::MultipleDynamicBind( id_, bindingExpr_->idLoc( ), Ast::THE_UNKNOWN_LOCATION );
818 (*sysBindings)->defaultUnit_ = val_;
821 void
822 Lang::DefaultUnitBinding::show( std::ostream & os ) const
824 os << Interaction::DYNAMIC_VARIABLE_PREFIX << id_ << ":<promise>" ;
827 void
828 Lang::DefaultUnitBinding::gcMark( Kernel::GCMarkedSet & marked )
830 val_->gcMark( marked );
834 Kernel::DefaultUnitDynamicVariableProperties::DefaultUnitDynamicVariableProperties( const char * _name )
835 : Kernel::DynamicVariableProperties( _name )
838 Kernel::DefaultUnitDynamicVariableProperties::~DefaultUnitDynamicVariableProperties( )
841 Kernel::VariableHandle
842 Kernel::DefaultUnitDynamicVariableProperties::fetch( const Kernel::PassedDyn & dyn ) const
844 throw Exceptions::MiscellaneousRequirement( "The default unit cannot be evaluated as a variable." );
847 void
848 Kernel::DefaultUnitDynamicVariableProperties::makeBinding( Kernel::VariableHandle val, const Ast::DynamicBindingExpression * bindingExpr, Kernel::EvalState * evalState ) const
850 if( ! val->isThunk( ) )
852 throw Exceptions::InternalError( "The default unit handle was not a thunk." );
855 Kernel::ContRef cont = evalState->cont_;
856 cont->takeValue( Kernel::ValueRef( new Lang::DefaultUnitBinding( name_, bindingExpr, RefCountPtr< const Kernel::PolarHandlePromise >( new Kernel::PolarHandleTruePromise( val->copyThunk( ) ) ) ) ),
857 evalState );
858 return;
862 Lang::TeXBleedBinding::TeXBleedBinding( const char * id, const Ast::DynamicBindingExpression * bindingExpr, Concrete::Length val )
863 : bindingExpr_( bindingExpr ), val_( val ), id_( id )
866 Lang::TeXBleedBinding::~TeXBleedBinding( )
869 void
870 Lang::TeXBleedBinding::bind( MapType & bindings, Kernel::SystemDynamicVariables ** sysBindings ) const
872 if( *sysBindings == 0 )
874 *sysBindings = new Kernel::SystemDynamicVariables( );
875 (*sysBindings)->TeX_bleed_ = val_;
876 return;
879 if( ! IS_NAN( (*sysBindings)->TeX_bleed_ ) )
881 throw Exceptions::MultipleDynamicBind( id_, bindingExpr_->idLoc( ), Ast::THE_UNKNOWN_LOCATION );
884 (*sysBindings)->TeX_bleed_ = val_;
887 void
888 Lang::TeXBleedBinding::show( std::ostream & os ) const
890 os << Interaction::DYNAMIC_VARIABLE_PREFIX << id_ << ":"
891 << val_ / Interaction::displayUnit << Interaction::displayUnitName ;
894 void
895 Lang::TeXBleedBinding::gcMark( Kernel::GCMarkedSet & marked )
900 Kernel::TeXBleedDynamicVariableProperties::TeXBleedDynamicVariableProperties( const char * _name )
901 : Kernel::DynamicVariableProperties( _name )
904 Kernel::TeXBleedDynamicVariableProperties::~TeXBleedDynamicVariableProperties( )
907 Kernel::VariableHandle
908 Kernel::TeXBleedDynamicVariableProperties::fetch( const Kernel::PassedDyn & dyn ) const
910 return Helpers::newValHandle( new Lang::Length( dyn->getTeXBleed( ) ) );
913 void
914 Kernel::TeXBleedDynamicVariableProperties::makeBinding( Kernel::VariableHandle val, const Ast::DynamicBindingExpression * bindingExpr, Kernel::EvalState * evalState ) const
916 RefCountPtr< const Lang::Length > len = val->getVal< const Lang::Length >( bindingExpr->exprLoc( ) );
917 Kernel::ContRef cont = evalState->cont_;
918 cont->takeValue( Kernel::ValueRef( new Lang::TeXBleedBinding( name_, bindingExpr, len->get( ) ) ),
919 evalState );
923 Lang::BlendSpaceBinding::BlendSpaceBinding( const char * id, const Ast::DynamicBindingExpression * bindingExpr, const RefCountPtr< const Lang::ColorSpace > & space )
924 : bindingExpr_( bindingExpr ), space_( space ), id_( id )
927 Lang::BlendSpaceBinding::~BlendSpaceBinding( )
930 void
931 Lang::BlendSpaceBinding::bind( MapType & bindings, Kernel::SystemDynamicVariables ** sysBindings ) const
933 if( *sysBindings == 0 )
935 *sysBindings = new Kernel::SystemDynamicVariables( );
936 (*sysBindings)->blendSpace_ = space_;
937 return;
940 if( (*sysBindings)->blendSpace_ != NullPtr< const Lang::ColorSpace >( ) )
942 throw Exceptions::MultipleDynamicBind( id_, bindingExpr_->idLoc( ), Ast::THE_UNKNOWN_LOCATION );
945 (*sysBindings)->blendSpace_ = space_;
948 void
949 Lang::BlendSpaceBinding::show( std::ostream & os ) const
951 os << Interaction::DYNAMIC_VARIABLE_PREFIX << id_ << "" ;
952 space_->show( os );
955 void
956 Lang::BlendSpaceBinding::gcMark( Kernel::GCMarkedSet & marked )
961 Kernel::BlendSpaceDynamicVariableProperties::BlendSpaceDynamicVariableProperties( const char * _name )
962 : Kernel::DynamicVariableProperties( _name )
965 Kernel::BlendSpaceDynamicVariableProperties::~BlendSpaceDynamicVariableProperties( )
968 Kernel::VariableHandle
969 Kernel::BlendSpaceDynamicVariableProperties::fetch( const Kernel::PassedDyn & dyn ) const
971 return Kernel::VariableHandle( new Kernel::Variable( dyn->getBlendSpace( ) ) );
974 void
975 Kernel::BlendSpaceDynamicVariableProperties::makeBinding( Kernel::VariableHandle val, const Ast::DynamicBindingExpression * bindingExpr, Kernel::EvalState * evalState ) const
977 RefCountPtr< const Lang::ColorSpace > space = val->getVal< const Lang::ColorSpace >( bindingExpr->exprLoc( ) );
978 if( ! space->isBlendable( ) )
980 throw Exceptions::OutOfRange( bindingExpr->exprLoc( ), strrefdup( "This color space cannot be used in blending." ) );
983 Kernel::ContRef cont = evalState->cont_;
984 cont->takeValue( Kernel::ValueRef( new Lang::BlendSpaceBinding( name_, bindingExpr, space ) ),
985 evalState );
989 Kernel::DynamicEnvironment::KeyType Kernel::DynamicEnvironment::nextKey( 0 );
991 Kernel::DynamicEnvironment::KeyType
992 Kernel::DynamicEnvironment::getFreshKey( )
994 ++nextKey;
995 return nextKey;
1000 Lang::DynamicExpression::DynamicExpression( Kernel::PassedEnv env, Ast::Expression * expr )
1001 : env_( env ), expr_( expr )
1004 Lang::DynamicExpression::~DynamicExpression( )
1007 RefCountPtr< const Lang::Class > Lang::DynamicExpression::TypeID( new Lang::SystemFinalClass( strrefdup( "DynamicExpression" ) ) );
1008 TYPEINFOIMPL( DynamicExpression );
1010 void
1011 Lang::DynamicExpression::evalHelper( Kernel::EvalState * evalState ) const
1013 evalState->env_ = env_;
1014 evalState->expr_ = expr_;
1017 void
1018 Lang::DynamicExpression::gcMark( Kernel::GCMarkedSet & marked )
1020 env_->gcMark( marked );
1024 void
1025 Kernel::registerDynamic( Kernel::Environment * env )
1027 env->initDefineDynamic( new Kernel::WidthDynamicVariableProperties( Lang::DYNAMIC_VARIABLE_ID_WIDTH ) );
1028 env->initDefineDynamic( new Kernel::CapStyleDynamicVariableProperties( "cap" ) );
1029 env->initDefineDynamic( new Kernel::JoinStyleDynamicVariableProperties( "join" ) );
1030 env->initDefineDynamic( new Kernel::MiterLimitDynamicVariableProperties( "miterlimit" ) );
1031 env->initDefineDynamic( new Kernel::StrokingDynamicVariableProperties( Lang::DYNAMIC_VARIABLE_ID_STROKING ) );
1032 env->initDefineDynamic( new Kernel::NonStrokingDynamicVariableProperties( Lang::DYNAMIC_VARIABLE_ID_NONSTROKING ) );
1033 env->initDefineDynamic( new Kernel::DashDynamicVariableProperties( "dash" ) );
1034 env->initDefineDynamic( new Kernel::BlendModeDynamicVariableProperties( "blend" ) );
1035 env->initDefineDynamic( new Kernel::AlphaDynamicVariableProperties( "nonstrokingalpha", false ) );
1036 env->initDefineDynamic( new Kernel::AlphaDynamicVariableProperties( "strokingalpha", true ) );
1038 env->initDefineDynamic( new Kernel::ReflectionsDynamicVariableProperties( "reflections" ) );
1039 env->initDefineDynamic( new Kernel::AutoIntensityDynamicVariableProperties( Lang::DYNAMIC_VARIABLE_ID_AUTOINTENSITY ) );
1040 env->initDefineDynamic( new Kernel::AutoScatteringDynamicVariableProperties( "autoscattering" ) );
1041 env->initDefineDynamic( new Kernel::ViewResolutionDynamicVariableProperties( "facetresolution" ) );
1042 env->initDefineDynamic( new Kernel::ShadeOrderDynamicVariableProperties( "shadeorder" ) );
1044 env->initDefineDynamic( new Kernel::CharacterSpacingDynamicVariableProperties( "text_characterspacing" ) );
1045 env->initDefineDynamic( new Kernel::WordSpacingDynamicVariableProperties( "text_wordspacing" ) );
1046 env->initDefineDynamic( new Kernel::HorizontalScalingDynamicVariableProperties( "text_horizontalscaling" ) );
1047 env->initDefineDynamic( new Kernel::LeadingDynamicVariableProperties( "text_leading" ) );
1048 env->initDefineDynamic( new Kernel::FontDynamicVariableProperties( Lang::DYNAMIC_VARIABLE_ID_TEXT_FONT ) );
1049 env->initDefineDynamic( new Kernel::TextSizeDynamicVariableProperties( Lang::DYNAMIC_VARIABLE_ID_TEXT_SIZE ) );
1050 env->initDefineDynamic( new Kernel::TextRenderingModeDynamicVariableProperties( "text_rendering" ) );
1051 env->initDefineDynamic( new Kernel::TextRiseDynamicVariableProperties( "text_rise" ) );
1052 env->initDefineDynamic( new Kernel::TextKnockoutDynamicVariableProperties( "text_knockout" ) );
1054 env->initDefineDynamic( new Kernel::TeXBleedDynamicVariableProperties( Lang::DYNAMIC_VARIABLE_ID_TEX_BLEED ) );
1056 env->initDefineDynamic( new Kernel::EyeZDynamicVariableProperties( Lang::DYNAMIC_VARIABLE_ID_EYEZ ) );
1057 env->initDefineDynamic( new Kernel::DefaultUnitDynamicVariableProperties( Lang::DYNAMIC_VARIABLE_ID_DEFAULT_UNIT ) );
1058 env->initDefineDynamic( new Kernel::BlendSpaceDynamicVariableProperties( Lang::DYNAMIC_VARIABLE_ID_BLEND_SPACE ) );