Mutators for Catalog states.
[shapes.git] / source / hottypes.cc
blob646777ed94854e5a24a3e13ce97c722711b622ce
1 #include "Shapes_Helpers_decls.h"
3 #include "hottypes.h"
4 #include "globals.h"
5 #include "continuations.h"
6 #include "texttypes.h"
7 #include "fontmetrics.h"
8 #include "tagtypes.h"
9 #include "isnan.h"
10 #include "pdfstructure.h"
11 #include "timetypes.h"
12 #include "shapescore.h"
14 #include <sstream>
15 #include <limits>
16 #include <sys/resource.h>
17 #include <cstdlib>
18 #include <cstring>
20 using namespace Shapes;
23 Lang::Hot::Hot::Hot( )
24 { }
26 Lang::Hot::~Hot( )
27 { }
29 RefCountPtr< const Lang::Class > Lang::Hot::TypeID( new Lang::SystemFinalClass( strrefdup( "Hot" ) ) );
30 TYPEINFOIMPL( Hot );
33 Lang::HotTriple::HotTriple( const RefCountPtr< const Lang::Value > & init, RefCountPtr< const Lang::Function > update, RefCountPtr< const Lang::Function > result )
34 : init_( init ), update_( update ), result_( result )
35 { }
37 Lang::HotTriple::~HotTriple( )
38 { }
40 Kernel::State *
41 Lang::HotTriple::newState( ) const
43 return new Kernel::WarmTriple( init_, update_, result_ );
46 void
47 Lang::HotTriple::gcMark( Kernel::GCMarkedSet & marked )
49 const_cast< Lang::Value * >( init_.getPtr( ) )->gcMark( marked );
50 const_cast< Lang::Function * >( update_.getPtr( ) )->gcMark( marked );
51 const_cast< Lang::Function * >( result_.getPtr( ) )->gcMark( marked );
56 Lang::HotRandomSeed::HotRandomSeed( size_t sz, Kernel::WarmRandomDevice * dev )
57 : sz_( sz ), state_( new char[ sz ] )
59 char * oldState = initstate( 1, state_, sz_ );
60 dev->read( state_, sz_ );
61 setstate( oldState );
64 Lang::HotRandomSeed::HotRandomSeed( size_t sz, unsigned long seed )
65 : sz_( sz ), state_( new char[ sz ] )
67 char * oldState = initstate( seed, state_, sz_ );
68 setstate( oldState );
71 Lang::HotRandomSeed::~HotRandomSeed( )
73 delete state_;
76 Kernel::State *
77 Lang::HotRandomSeed::newState( ) const
79 char * stateCopy = new char[ sz_ ];
80 memcpy( stateCopy, state_, sz_ );
81 return new Kernel::WarmRandomState( stateCopy ); // This handles ownership to the new state.
84 void
85 Lang::HotRandomSeed::gcMark( Kernel::GCMarkedSet & marked )
86 { }
91 Kernel::WarmTriple::WarmTriple( const RefCountPtr< const Lang::Value > & pile, RefCountPtr< const Lang::Function > update, RefCountPtr< const Lang::Function > result )
92 : pile_( pile ), update_( update ), result_( result )
93 { }
95 Kernel::WarmTriple::~WarmTriple( )
96 { }
98 RefCountPtr< const Lang::Class > Kernel::WarmTriple::TypeID( new Lang::SystemFinalClass( strrefdup( "#UserState" ) ) );
99 TYPEINFOIMPL_STATE( WarmTriple );
101 void
102 Kernel::WarmTriple::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
104 /* This seems dangerous. I have not verified that pile will still exist when the continuation below is invoked.
106 evalState->cont_ = Kernel::ContRef( new Kernel::StmtStoreValueContinuation( & pile_,
107 evalState->cont_,
108 callLoc ) );
109 update_->call( evalState, pile_, piece, callLoc );
112 void
113 Kernel::WarmTriple::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
115 /* The right continuation is set by the calling variable.
117 result_->call( evalState, pile_, callLoc );
120 void
121 Kernel::WarmTriple::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
123 /* The right continuation is set by the calling variable.
125 result_->call( evalState, pile_, callLoc );
128 void
129 Kernel::WarmTriple::gcMark( Kernel::GCMarkedSet & marked )
131 const_cast< Lang::Value * >( pile_.getPtr( ) )->gcMark( marked );
132 const_cast< Lang::Function * >( update_.getPtr( ) )->gcMark( marked );
133 const_cast< Lang::Function * >( result_.getPtr( ) )->gcMark( marked );
137 Kernel::WarmIgnore::WarmIgnore( )
140 Kernel::WarmIgnore::~WarmIgnore( )
143 RefCountPtr< const Lang::Class > Kernel::WarmIgnore::TypeID( new Lang::SystemFinalClass( strrefdup( "#Ignore" ) ) );
144 TYPEINFOIMPL_STATE( WarmIgnore );
146 void
147 Kernel::WarmIgnore::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
149 // Ignore piece!
151 Kernel::ContRef cont = evalState->cont_;
152 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
153 evalState );
156 void
157 Kernel::WarmIgnore::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
159 throw Exceptions::MiscellaneousRequirement( strrefdup( "An ignore state cannot be frozen." ) );
162 void
163 Kernel::WarmIgnore::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
165 throw Exceptions::MiscellaneousRequirement( strrefdup( "An ignore state cannot be peeked." ) );
168 void
169 Kernel::WarmIgnore::gcMark( Kernel::GCMarkedSet & marked )
173 Kernel::WarmOstream::WarmOstream( std::ostream & os )
174 : os_( os )
177 Kernel::WarmOstream::~WarmOstream( )
180 RefCountPtr< const Lang::Class > Kernel::WarmOstream::TypeID( new Lang::SystemFinalClass( strrefdup( "#OutputStream" ) ) );
181 TYPEINFOIMPL_STATE( WarmOstream );
183 void
184 Kernel::WarmOstream::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
186 piece->show( os_ );
187 Kernel::ContRef cont = evalState->cont_;
188 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
189 evalState );
192 void
193 Kernel::WarmOstream::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
195 throw Exceptions::MiscellaneousRequirement( strrefdup( "A warm ostream cannot be frozen." ) );
198 void
199 Kernel::WarmOstream::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
201 throw Exceptions::MiscellaneousRequirement( strrefdup( "A warm ostream cannot be peeked." ) );
204 void
205 Kernel::WarmOstream::gcMark( Kernel::GCMarkedSet & marked )
209 Kernel::Warm_ostringstream::Warm_ostringstream( )
212 Kernel::Warm_ostringstream::~Warm_ostringstream( )
215 RefCountPtr< const Lang::Class > Kernel::Warm_ostringstream::TypeID( new Lang::SystemFinalClass( strrefdup( "#StringConcatenator" ) ) );
216 TYPEINFOIMPL_STATE( Warm_ostringstream );
218 void
219 Kernel::Warm_ostringstream::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
221 piece->show( os_ );
222 Kernel::ContRef cont = evalState->cont_;
223 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
224 evalState );
227 void
228 Kernel::Warm_ostringstream::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
230 Kernel::ContRef cont = evalState->cont_;
231 cont->takeValue( Kernel::ValueRef( new Lang::String( strrefdup( os_.str( ).c_str( ) ) ) ),
232 evalState );
235 void
236 Kernel::Warm_ostringstream::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
238 Kernel::ContRef cont = evalState->cont_;
239 cont->takeValue( Kernel::ValueRef( new Lang::String( strrefdup( os_.str( ).c_str( ) ) ) ),
240 evalState );
243 void
244 Kernel::Warm_ostringstream::gcMark( Kernel::GCMarkedSet & marked )
247 namespace Shapes
249 namespace Kernel
252 template< class T >
253 class Mutator_erase : public Lang::CoreFunction
255 public:
256 Mutator_erase( const char * title )
257 : CoreFunction( title, new Kernel::EvaluatedFormals( title, true ) )
260 virtual void
261 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
263 args.applyDefaults( );
265 typedef T StateType;
266 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
267 state->erase( );
269 Kernel::ContRef cont = evalState->cont_;
270 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
271 evalState );
275 template< class T >
276 class Mutator_remove : public Lang::CoreFunction
278 public:
279 Mutator_remove( const char * title )
280 : CoreFunction( title, new Kernel::EvaluatedFormals( title, true ) )
282 formals_->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE );
284 virtual void
285 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
287 args.applyDefaults( );
289 typedef const Lang::Symbol KeyType;
290 RefCountPtr< KeyType > key = Helpers::down_cast_CoreArgument< KeyType >( title_, args, 0, callLoc );
292 typedef T StateType;
293 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
294 state->remove( key->getKey( ) );
296 Kernel::ContRef cont = evalState->cont_;
297 cont->takeValue( Lang::THE_VOID,
298 evalState );
306 Kernel::WarmGroup2D::WarmGroup2D( )
307 : pile_( Lang::THE_NULL2D )
310 Kernel::WarmGroup2D::~WarmGroup2D( )
313 void
314 WarmGroup2D_register_mutators( Lang::SystemFinalClass * dstClass )
316 dstClass->registerMutator( new Kernel::Mutator_erase< Kernel::WarmGroup2D >( "erase" ) );
317 dstClass->registerMutator( new Kernel::Mutator_remove< Kernel::WarmGroup2D >( "remove" ) );
320 RefCountPtr< const Lang::Class > Kernel::WarmGroup2D::TypeID( new Lang::SystemFinalClass( strrefdup( "#Group2D" ), WarmGroup2D_register_mutators ) );
321 TYPEINFOIMPL_STATE( WarmGroup2D );
324 void
325 Kernel::WarmGroup2D::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
327 typedef const Lang::Drawable2D ArgType;
328 RefCountPtr< ArgType > arg = Helpers::down_cast< ArgType >( piece, callLoc );
331 /* For objects of user-defined type, we also check that the class inherits from Drawable.
333 typedef const Lang::Instance UserType;
334 UserType * obj = dynamic_cast< UserType * >( arg.getPtr( ) );
335 if( obj != 0 )
337 if( ! obj->getClass( )->method_isa( Lang::Drawable2D::TypeID ) )
339 throw Exceptions::TypeMismatch( callLoc, "2D insertion", piece->getTypeName( ), ArgType::staticTypeName( ) );
344 pile_ = RefCountPtr< const Lang::Group2D >( new Lang::GroupPair2D( arg,
345 pile_,
346 dyn->getGraphicsState( ) ) );
347 Kernel::ContRef cont = evalState->cont_;
348 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
349 evalState );
352 void
353 Kernel::WarmGroup2D::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
355 Kernel::ContRef cont = evalState->cont_;
356 cont->takeValue( pile_,
357 evalState );
360 void
361 Kernel::WarmGroup2D::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
363 Kernel::ContRef cont = evalState->cont_;
364 cont->takeValue( pile_,
365 evalState );
368 void
369 Kernel::WarmGroup2D::erase( )
371 pile_ = Lang::THE_NULL2D;
374 void
375 Kernel::WarmGroup2D::remove( Lang::Symbol::KeyType key )
377 pile_ = pile_->removeShallow( key );
380 void
381 Kernel::WarmGroup2D::gcMark( Kernel::GCMarkedSet & marked )
383 const_cast< Lang::Group2D * >( pile_.getPtr( ) )->gcMark( marked );
388 Kernel::WarmGroup3D::WarmGroup3D( )
389 : pile_( Lang::THE_NULL3D )
392 Kernel::WarmGroup3D::~WarmGroup3D( )
395 void
396 WarmGroup3D_register_mutators( Lang::SystemFinalClass * dstClass )
398 dstClass->registerMutator( new Kernel::Mutator_erase< Kernel::WarmGroup3D >( "erase" ) );
399 dstClass->registerMutator( new Kernel::Mutator_remove< Kernel::WarmGroup3D >( "remove" ) );
402 RefCountPtr< const Lang::Class > Kernel::WarmGroup3D::TypeID( new Lang::SystemFinalClass( strrefdup( "#Group3D" ), WarmGroup3D_register_mutators ) );
403 TYPEINFOIMPL_STATE( WarmGroup3D );
405 void
406 Kernel::WarmGroup3D::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
408 pile_ = RefCountPtr< const Lang::Group3D >( new Lang::GroupPair3D( Helpers::down_cast< const Lang::Drawable3D >( piece, callLoc ),
409 pile_,
410 dyn->getGraphicsState( ) ) );
411 Kernel::ContRef cont = evalState->cont_;
412 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
413 evalState );
416 void
417 Kernel::WarmGroup3D::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
419 Kernel::ContRef cont = evalState->cont_;
420 cont->takeValue( pile_,
421 evalState );
424 void
425 Kernel::WarmGroup3D::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
427 Kernel::ContRef cont = evalState->cont_;
428 cont->takeValue( pile_,
429 evalState );
432 void
433 Kernel::WarmGroup3D::erase( )
435 pile_ = Lang::THE_NULL3D;
438 void
439 Kernel::WarmGroup3D::remove( Lang::Symbol::KeyType key )
441 pile_ = pile_->removeShallow( key );
444 void
445 Kernel::WarmGroup3D::gcMark( Kernel::GCMarkedSet & marked )
447 const_cast< Lang::Group3D * >( pile_.getPtr( ) )->gcMark( marked );
451 Kernel::WarmGroupLights::WarmGroupLights( )
452 : pile_( Lang::THE_NULL_LIGHTS )
455 Kernel::WarmGroupLights::~WarmGroupLights( )
458 RefCountPtr< const Lang::Class > Kernel::WarmGroupLights::TypeID( new Lang::SystemFinalClass( strrefdup( "#GroupLights" ) ) );
459 TYPEINFOIMPL_STATE( WarmGroupLights );
461 void
462 Kernel::WarmGroupLights::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
464 pile_ = RefCountPtr< const Lang::LightGroup >( new Lang::LightPair( Helpers::down_cast< const Lang::LightSource >( piece, callLoc ),
465 pile_ ) );
466 Kernel::ContRef cont = evalState->cont_;
467 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
468 evalState );
471 void
472 Kernel::WarmGroupLights::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
474 Kernel::ContRef cont = evalState->cont_;
475 cont->takeValue( pile_,
476 evalState );
479 void
480 Kernel::WarmGroupLights::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
482 Kernel::ContRef cont = evalState->cont_;
483 cont->takeValue( pile_,
484 evalState );
487 void
488 Kernel::WarmGroupLights::gcMark( Kernel::GCMarkedSet & marked )
490 const_cast< Lang::LightGroup * >( pile_.getPtr( ) )->gcMark( marked );
494 Kernel::WarmZBuf::WarmZBuf( )
497 Kernel::WarmZBuf::~WarmZBuf( )
500 RefCountPtr< const Lang::Class > Kernel::WarmZBuf::TypeID( new Lang::SystemFinalClass( strrefdup( "#ZBuf" ) ) );
501 TYPEINFOIMPL_STATE( WarmZBuf );
503 void
504 Kernel::WarmZBuf::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
508 typedef const Lang::Drawable3D ArgType;
509 RefCountPtr< ArgType > drawable = Helpers::try_cast_CoreArgument< ArgType >( piece );
512 drawable->polygonize( pile_.getPtr( ), strokePile_.getPtr( ), evalState->dyn_, Lang::THE_3D_IDENTITY, drawable );
514 catch( const char * ball )
516 std::ostringstream oss;
517 oss << "Conversion to polygon failed with: " << ball ;
518 throw Exceptions::OutOfRange( callLoc, strrefdup( oss ) );
520 Kernel::ContRef cont = evalState->cont_;
521 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
522 evalState );
523 return;
525 catch( const NonLocalExit::NotThisType & ball )
527 /* Wrong type; never mind!.. but see below!
533 lightPile_->push_back( Helpers::try_cast_CoreArgument< const Lang::LightSource >( piece ) );
534 Kernel::ContRef cont = evalState->cont_;
535 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
536 evalState );
537 return;
539 catch( const NonLocalExit::NotThisType & ball )
541 /* Wrong type; never mind!.. but see below!
547 typedef const Lang::LightGroup ArgType;
548 RefCountPtr< ArgType > lights = Helpers::try_cast_CoreArgument< ArgType >( piece );
550 while( ! lights->isNull( ) )
552 typedef const Lang::LightPair PairType;
553 RefCountPtr< PairType > p = lights.down_cast< PairType >( );
554 lightPile_->push_back( p->car( ) );
555 lights = p->cdr( );
558 Kernel::ContRef cont = evalState->cont_;
559 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
560 evalState );
561 return;
563 catch( const NonLocalExit::NotThisType & ball )
565 /* Wrong type; never mind!.. but see below!
569 throw Exceptions::TypeMismatch( callLoc, piece->getTypeName( ), Helpers::typeSetString( Lang::Drawable3D::staticTypeName( ), Lang::LightSource::staticTypeName( ) ) );
572 void
573 Kernel::WarmZBuf::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
575 Kernel::ContRef cont = evalState->cont_;
576 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::ZBuf( pile_, strokePile_, lightPile_, evalState->dyn_->getGraphicsState( ) ) ),
577 evalState );
580 void
581 Kernel::WarmZBuf::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
583 throw Exceptions::MiscellaneousRequirement( strrefdup( "A z-buffer state cannot be peeked." ) );
586 void
587 Kernel::WarmZBuf::gcMark( Kernel::GCMarkedSet & marked )
590 typedef typeof *pile_ ListType;
591 for( ListType::const_iterator i = pile_->begin( ); i != pile_->end( ); ++i )
593 const_cast< Computation::PaintedPolygon3D * >( i->getPtr( ) )->gcMark( marked );
596 // {
597 // typedef typeof *strokePile_ ListType;
598 // for( ListType::const_iterator i = strokePile_->begin( ); i != strokePile_->end( ); ++i )
599 // {
600 // const_cast< Computation::StrokedLine3D * >( i->getPtr( ) )->gcMark( marked );
601 // }
602 // }
604 typedef typeof *lightPile_ ListType;
605 for( ListType::const_iterator i = lightPile_->begin( ); i != lightPile_->end( ); ++i )
607 const_cast< Lang::LightSource * >( i->getPtr( ) )->gcMark( marked );
613 Kernel::WarmZSorter::WarmZSorter( )
616 Kernel::WarmZSorter::~WarmZSorter( )
619 RefCountPtr< const Lang::Class > Kernel::WarmZSorter::TypeID( new Lang::SystemFinalClass( strrefdup( "#ZSorter" ) ) );
620 TYPEINFOIMPL_STATE( WarmZSorter );
622 void
623 Kernel::WarmZSorter::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
627 typedef const Lang::Drawable3D ArgType;
628 RefCountPtr< ArgType > drawable = Helpers::try_cast_CoreArgument< ArgType >( piece );
631 drawable->polygonize( pile_.getPtr( ), strokePile_.getPtr( ), evalState->dyn_, Lang::THE_3D_IDENTITY, drawable );
633 catch( const char * ball )
635 std::ostringstream oss;
636 oss << "Conversion to polygon failed with: " << ball ;
637 throw Exceptions::OutOfRange( callLoc, strrefdup( oss ) );
639 Kernel::ContRef cont = evalState->cont_;
640 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
641 evalState );
642 return;
644 catch( const NonLocalExit::NotThisType & ball )
646 /* Wrong type; never mind!.. but see below!
652 lightPile_->push_back( Helpers::try_cast_CoreArgument< const Lang::LightSource >( piece ) );
653 Kernel::ContRef cont = evalState->cont_;
654 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
655 evalState );
656 return;
658 catch( const NonLocalExit::NotThisType & ball )
660 /* Wrong type; never mind!.. but see below!
666 typedef const Lang::LightGroup ArgType;
667 RefCountPtr< ArgType > lights = Helpers::try_cast_CoreArgument< ArgType >( piece );
669 while( ! lights->isNull( ) )
671 typedef const Lang::LightPair PairType;
672 RefCountPtr< PairType > p = lights.down_cast< PairType >( );
673 lightPile_->push_back( p->car( ) );
674 lights = p->cdr( );
677 Kernel::ContRef cont = evalState->cont_;
678 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
679 evalState );
680 return;
682 catch( const NonLocalExit::NotThisType & ball )
684 /* Wrong type; never mind!.. but see below!
688 throw Exceptions::TypeMismatch( callLoc, piece->getTypeName( ), Helpers::typeSetString( Lang::Drawable3D::staticTypeName( ), Lang::LightSource::staticTypeName( ) ) );
691 void
692 Kernel::WarmZSorter::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
694 Kernel::ContRef cont = evalState->cont_;
695 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::ZSorter( pile_, strokePile_, lightPile_, evalState->dyn_->getGraphicsState( ) ) ),
696 evalState );
699 void
700 Kernel::WarmZSorter::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
702 throw Exceptions::MiscellaneousRequirement( strrefdup( "A z-sorter state cannot be peeked." ) );
705 void
706 Kernel::WarmZSorter::gcMark( Kernel::GCMarkedSet & marked )
709 typedef typeof *pile_ ListType;
710 for( ListType::const_iterator i = pile_->begin( ); i != pile_->end( ); ++i )
712 const_cast< Computation::PaintedPolygon3D * >( i->getPtr( ) )->gcMark( marked );
715 // {
716 // typedef typeof *strokePile_ ListType;
717 // for( ListType::const_iterator i = strokePile_->begin( ); i != strokePile_->end( ); ++i )
718 // {
719 // const_cast< Computation::StrokedLine3D * >( i->getPtr( ) )->gcMark( marked );
720 // }
721 // }
723 typedef typeof *lightPile_ ListType;
724 for( ListType::const_iterator i = lightPile_->begin( ); i != lightPile_->end( ); ++i )
726 const_cast< Lang::LightSource * >( i->getPtr( ) )->gcMark( marked );
732 Kernel::WarmTimer::WarmTimer( )
734 rusage ru;
735 int res = getrusage( RUSAGE_SELF, &ru );
736 if( res != 0 )
738 throw Exceptions::InternalError( strrefdup( "getrusage failed." ) );
740 start_ = ru.ru_utime;
743 Kernel::WarmTimer::~WarmTimer( )
746 RefCountPtr< const Lang::Class > Kernel::WarmTimer::TypeID( new Lang::SystemFinalClass( strrefdup( "#Timer" ) ) );
747 TYPEINFOIMPL_STATE( WarmTimer );
749 void
750 Kernel::WarmTimer::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
752 throw Exceptions::MiscellaneousRequirement( strrefdup( "A warm timer does not accept values. Please freeze to obtain the number of seconds since creation." ) );
755 void
756 Kernel::WarmTimer::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
758 rusage ru;
759 int res = getrusage( RUSAGE_SELF, &ru );
760 if( res != 0 )
762 throw Exceptions::InternalError( strrefdup( "getrusage failed." ) );
764 timeval stop = ru.ru_utime;
765 double time1 = start_.tv_usec / 1000000.0 + start_.tv_sec;
766 double time2 = stop.tv_usec / 1000000.0 + stop.tv_sec;
768 Kernel::ContRef cont = evalState->cont_;
769 cont->takeValue( Kernel::ValueRef( new Lang::Float( time2 - time1 ) ),
770 evalState );
773 void
774 Kernel::WarmTimer::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
776 rusage ru;
777 int res = getrusage( RUSAGE_SELF, &ru );
778 if( res != 0 )
780 throw Exceptions::InternalError( strrefdup( "grtrusage failed." ) );
782 timeval stop = ru.ru_utime;
783 double time1 = start_.tv_usec / 1000000.0 + start_.tv_sec;
784 double time2 = stop.tv_usec / 1000000.0 + stop.tv_sec;
786 Kernel::ContRef cont = evalState->cont_;
787 cont->takeValue( Kernel::ValueRef( new Lang::Float( time2 - time1 ) ),
788 evalState );
791 void
792 Kernel::WarmTimer::gcMark( Kernel::GCMarkedSet & marked )
796 Kernel::WarmText::WarmText( )
799 Kernel::WarmText::~WarmText( )
802 RefCountPtr< const Lang::Class > Kernel::WarmText::TypeID( new Lang::SystemFinalClass( strrefdup( "#Text" ) ) );
803 TYPEINFOIMPL_STATE( WarmText );
805 void
806 Kernel::WarmText::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
810 typedef const Lang::TextOperation ArgType;
811 pile_->push_back( Helpers::try_cast_CoreArgument< ArgType >( piece ) );
812 Kernel::ContRef cont = evalState->cont_;
813 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
814 evalState );
815 return;
817 catch( const NonLocalExit::NotThisType & ball )
819 /* Wrong type; never mind!.. but see below!
825 typedef const Lang::String ArgType;
826 RefCountPtr< ArgType > str = Helpers::try_cast_CoreArgument< ArgType >( piece );
827 Lang::KernedText * text = new Lang::KernedText( evalState->dyn_->getTextState( ), evalState->dyn_->getGraphicsState( ) );
828 text->pushString( str );
829 pile_->push_back( RefCountPtr< const Lang::TextOperation >( text ) );
830 Kernel::ContRef cont = evalState->cont_;
831 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
832 evalState );
833 return;
835 catch( const NonLocalExit::NotThisType & ball )
837 /* Wrong type; never mind!.. but see below!
843 typedef const Lang::Transform2D ArgType;
844 RefCountPtr< ArgType > tf = Helpers::try_cast_CoreArgument< ArgType >( piece );
845 pile_->push_back( RefCountPtr< const Lang::TextOperation >( new Lang::TextMoveto( tf ) ) );
846 Kernel::ContRef cont = evalState->cont_;
847 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
848 evalState );
849 return;
851 catch( const NonLocalExit::NotThisType & ball )
853 /* Wrong type; never mind!.. but see below!
859 typedef const Lang::Coords2D ArgType;
860 RefCountPtr< ArgType > t = Helpers::try_cast_CoreArgument< ArgType >( piece );
861 pile_->push_back( RefCountPtr< const Lang::TextOperation >( new Lang::TextNewline( t->x_.get( ), t->y_.get( ) ) ) );
862 Kernel::ContRef cont = evalState->cont_;
863 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
864 evalState );
865 return;
867 catch( const NonLocalExit::NotThisType & ball )
869 /* Wrong type; never mind!.. but see below!
875 typedef const Lang::FloatPair ArgType;
876 RefCountPtr< ArgType > t = Helpers::try_cast_CoreArgument< ArgType >( piece );
877 Concrete::Length sz = evalState->dyn_->getTextState( )->size_;
878 pile_->push_back( RefCountPtr< const Lang::TextOperation >( new Lang::TextNewline( sz * t->x_, sz * t->y_ ) ) );
879 Kernel::ContRef cont = evalState->cont_;
880 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
881 evalState );
882 return;
884 catch( const NonLocalExit::NotThisType & ball )
886 /* Wrong type; never mind!.. but see below!
890 throw Exceptions::TypeMismatch( callLoc, piece->getTypeName( ), Helpers::typeSetString( Lang::TextOperation::staticTypeName( ), Lang::String::staticTypeName( ) ) );
893 void
894 Kernel::WarmText::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
896 if( pile_->empty( ) )
898 Kernel::ContRef cont = evalState->cont_;
899 cont->takeValue( Lang::THE_NULL2D,
900 evalState );
901 return;
904 Concrete::Length xmin = Concrete::HUGE_LENGTH;
905 Concrete::Length xmax = -Concrete::HUGE_LENGTH;
906 Concrete::Length ymin = Concrete::HUGE_LENGTH;
907 Concrete::Length ymax = -Concrete::HUGE_LENGTH;
910 Lang::Transform2D textMatrix( 1, 0, 0, 1, 0, 0 );
911 Lang::Transform2D textLineMatrix( 1, 0, 0, 1, 0, 0 );
912 typedef typeof *pile_ ListType;
913 for( ListType::const_iterator i = pile_->begin( ); i != pile_->end( ); ++i )
915 (*i)->measure( & textMatrix, & textLineMatrix, & xmin, & ymin, & xmax, & ymax );
919 Lang::ElementaryPath2D * bbox = new Lang::ElementaryPath2D;
921 if( xmin < Concrete::HUGE_LENGTH )
923 bbox->push_back( new Concrete::PathPoint2D( xmin, ymin ) );
924 bbox->push_back( new Concrete::PathPoint2D( xmin, ymax ) );
925 bbox->push_back( new Concrete::PathPoint2D( xmax, ymax ) );
926 bbox->push_back( new Concrete::PathPoint2D( xmax, ymin ) );
927 bbox->close( );
930 Kernel::ContRef cont = evalState->cont_;
931 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::Text( evalState->dyn_->getGraphicsState( ),
932 evalState->dyn_->getTextState( ),
933 pile_,
934 RefCountPtr< const Lang::ElementaryPath2D >( bbox ) ) ),
935 evalState );
938 void
939 Kernel::WarmText::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
941 throw Exceptions::MiscellaneousRequirement( strrefdup( "A text graphics state cannot be peeked." ) );
944 void
945 Kernel::WarmText::gcMark( Kernel::GCMarkedSet & marked )
947 typedef typeof *pile_ ListType;
948 for( ListType::const_iterator i = pile_->begin( ); i != pile_->end( ); ++i )
950 const_cast< Lang::TextOperation * >( i->getPtr( ) )->gcMark( marked );
955 Kernel::WarmType3Font::WarmType3Font( )
956 : metrics_( new FontMetrics::BaseFont( ) ), size_( -1 )
958 metrics_->capHeight_ = std::numeric_limits< double >::signaling_NaN( );
959 metrics_->xHeight_ = std::numeric_limits< double >::signaling_NaN( );
960 metrics_->ascender_ = std::numeric_limits< double >::signaling_NaN( );
961 metrics_->descender_ = std::numeric_limits< double >::signaling_NaN( );
962 metrics_->leading_ = std::numeric_limits< double >::signaling_NaN( );
963 metrics_->stdHW_ = std::numeric_limits< double >::signaling_NaN( );
964 metrics_->stdVW_ = std::numeric_limits< double >::signaling_NaN( );
965 metrics_->fontBBoxXMin_ = 0;
966 metrics_->fontBBoxXMax_ = -1;
968 metrics_->horizontalMetrics_ = RefCountPtr< FontMetrics::WritingDirectionMetrics >( new FontMetrics::WritingDirectionMetrics( ) );
969 metrics_->horizontalMetrics_->underlinePosition_ = std::numeric_limits< double >::signaling_NaN( );
970 metrics_->horizontalMetrics_->underlineThickness_ = std::numeric_limits< double >::signaling_NaN( );
971 metrics_->horizontalMetrics_->italicAngleRadians_ = std::numeric_limits< double >::signaling_NaN( );
974 Kernel::WarmType3Font::~WarmType3Font( )
977 RefCountPtr< const Lang::Class > Kernel::WarmType3Font::TypeID( new Lang::SystemFinalClass( strrefdup( "#Type3Font" ) ) );
978 TYPEINFOIMPL_STATE( WarmType3Font );
980 void
981 Kernel::WarmType3Font::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
985 typedef const Lang::Type3Glyph ArgType;
986 glyphs_.push_back( Helpers::try_cast_CoreArgument< ArgType >( piece ) );
987 Kernel::ContRef cont = evalState->cont_;
988 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
989 evalState );
990 return;
992 catch( const NonLocalExit::NotThisType & ball )
994 /* Wrong type; never mind!.. but see below!
1000 typedef const Lang::KernedText ArgType;
1001 kernings_.push_back( Helpers::try_cast_CoreArgument< ArgType >( piece ) );
1002 Kernel::ContRef cont = evalState->cont_;
1003 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
1004 evalState );
1005 return;
1007 catch( const NonLocalExit::NotThisType & ball )
1009 /* Wrong type; never mind!.. but see below!
1015 typedef const Lang::TaggedValue2D ArgType;
1016 RefCountPtr< ArgType > taggedVal = Helpers::try_cast_CoreArgument< ArgType >( piece );
1018 RefCountPtr< const char > tagMem = Lang::Symbol::nameFromKey( taggedVal->key( ) );
1019 const char * tag = tagMem.getPtr( );
1020 RefCountPtr< const Lang::Value > val = taggedVal->val( );
1022 if( strcmp( tag, "size" ) == 0 )
1024 if( size_ > 0 )
1026 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1028 typedef const Lang::Length ValType;
1029 size_ = Helpers::down_cast< ValType >( val, callLoc )->get( );
1030 if( ! ( size_ > 0 ) )
1032 throw Exceptions::OutOfRange( callLoc, "The size must be positive." );
1035 else if( strcmp( tag, "FontName" ) == 0 )
1037 if( metrics_->fontName_ != NullPtr< const char >( ) )
1039 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1041 typedef const Lang::Symbol ValType;
1042 metrics_->fontName_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1044 else if( strcmp( tag, "FullName" ) == 0 )
1046 if( metrics_->fullName_ != NullPtr< const char >( ) )
1048 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1050 typedef const Lang::String ValType;
1051 metrics_->fullName_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1053 else if( strcmp( tag, "FamilyName" ) == 0 )
1055 if( metrics_->familyName_ != NullPtr< const char >( ) )
1057 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1059 typedef const Lang::Symbol ValType;
1060 metrics_->familyName_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1062 else if( strcmp( tag, "Weight" ) == 0 )
1066 typedef const Lang::Symbol ValType;
1067 RefCountPtr< const char > typedVal = Helpers::try_cast_CoreArgument< ValType >( val )->name( );
1068 if( metrics_->weight_ != NullPtr< const char >( ) )
1070 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1072 static std::set< const char *, charPtrLess > legalStretchValues;
1073 if( legalStretchValues.empty( ) )
1075 initializeLegalStrechValues( & legalStretchValues );
1077 if( legalStretchValues.find( typedVal.getPtr( ) ) == legalStretchValues.end( ) )
1079 throw Exceptions::OutOfRange( callLoc, "The 'Weight value is illegal. Please refer to the PDF specification." );
1081 metrics_->weight_ = typedVal;
1082 goto OK;
1084 catch( const NonLocalExit::NotThisType & ball )
1086 /* Wrong type; never mind!.. but see below!
1092 typedef const Lang::Integer ValType;
1093 RefCountPtr< ValType > casted_val = Helpers::try_cast_CoreArgument< ValType >( val );
1094 if( metrics_->weightNumber_ > 0 )
1096 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1098 if( casted_val->val_ % 100 != 0 )
1100 throw Exceptions::OutOfRange( callLoc, "The 'Weight number must be divisible by 100." );
1102 if( casted_val->val_ < 100 || casted_val->val_ > 900 )
1104 throw Exceptions::OutOfRange( callLoc, "The 'Weight number must be in the range [ 100, 900 ]." );
1106 metrics_->weightNumber_ = casted_val->val_;
1107 goto OK;
1109 catch( const NonLocalExit::NotThisType & ball )
1111 /* Wrong type; never mind!.. but see below!
1115 throw Exceptions::TypeMismatch( callLoc, val->getTypeName( ), Helpers::typeSetString( Lang::String::staticTypeName( ), Lang::Integer::staticTypeName( ) ) );
1117 else if( strcmp( tag, "Version" ) == 0 )
1119 if( metrics_->version_ != NullPtr< const char >( ) )
1121 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1123 typedef const Lang::String ValType;
1124 metrics_->version_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1126 else if( strcmp( tag, "Notice" ) == 0 )
1128 if( metrics_->notice_ != NullPtr< const char >( ) )
1130 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1132 typedef const Lang::String ValType;
1133 metrics_->notice_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1135 else if( strcmp( tag, "EncodingScheme" ) == 0 )
1137 if( metrics_->encodingScheme_ != NullPtr< const char >( ) )
1139 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1141 typedef const Lang::Symbol ValType;
1142 metrics_->encodingScheme_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1144 else if( strcmp( tag, "CharacterSet" ) == 0 )
1146 if( metrics_->characterSet_ != NullPtr< const char >( ) )
1148 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1150 typedef const Lang::Symbol ValType;
1151 metrics_->characterSet_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1153 else if( strcmp( tag, "Comment" ) == 0 )
1155 typedef const Lang::String ValType;
1156 RefCountPtr< ValType > typedVal = Helpers::down_cast< ValType >( val, callLoc );
1157 metrics_->comments_.push_back( FontMetrics::AFM::AssortedInfo( tagMem, typedVal->val_ ) );
1159 else if( strcmp( tag, "CapHeight" ) == 0 )
1161 if( ! IS_NAN( metrics_->capHeight_ ) )
1163 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1165 if( ! ( size_ > 0 ) )
1167 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1169 typedef const Lang::Length ValType;
1170 metrics_->capHeight_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1172 else if( strcmp( tag, "XHeight" ) == 0 )
1174 if( ! IS_NAN( metrics_->xHeight_ ) )
1176 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1178 if( ! ( size_ > 0 ) )
1180 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1182 typedef const Lang::Length ValType;
1183 metrics_->xHeight_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1185 else if( strcmp( tag, "Ascent" ) == 0 )
1187 if( ! IS_NAN( metrics_->ascender_ ) )
1189 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1191 if( ! ( size_ > 0 ) )
1193 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1195 typedef const Lang::Length ValType;
1196 metrics_->ascender_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1198 else if( strcmp( tag, "Descent" ) == 0 )
1200 if( ! IS_NAN( metrics_->descender_ ) )
1202 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1204 if( ! ( size_ > 0 ) )
1206 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1208 typedef const Lang::Length ValType;
1209 metrics_->descender_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1211 else if( strcmp( tag, "Leading" ) == 0 )
1213 if( ! IS_NAN( metrics_->leading_ ) )
1215 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1217 if( ! ( size_ > 0 ) )
1219 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1221 typedef const Lang::Length ValType;
1222 metrics_->leading_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1224 else if( strcmp( tag, "StemH" ) == 0 )
1226 if( ! IS_NAN( metrics_->stdHW_ ) )
1228 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1230 if( ! ( size_ > 0 ) )
1232 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1234 typedef const Lang::Length ValType;
1235 metrics_->stdHW_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1237 else if( strcmp( tag, "StemV" ) == 0 )
1239 if( ! IS_NAN( metrics_->stdVW_ ) )
1241 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1243 if( ! ( size_ > 0 ) )
1245 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1247 typedef const Lang::Length ValType;
1248 metrics_->stdVW_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1250 else if( strcmp( tag, "FontBBox" ) == 0 )
1252 if( metrics_->fontBBoxXMax_ >= metrics_->fontBBoxXMin_ )
1254 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1256 if( ! ( size_ > 0 ) )
1258 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1260 typedef const Lang::ElementaryPath2D ValType;
1261 RefCountPtr< ValType > casted_val = Helpers::elementaryPathTry2D( val );
1262 Concrete::Coords2D llcorner( 0, 0 );
1263 Concrete::Coords2D urcorner( 0, 0 );
1264 if( ! casted_val->boundingRectangle( & llcorner, & urcorner ) )
1266 throw Exceptions::OutOfRange( callLoc, "The path was empty." );
1268 metrics_->fontBBoxXMin_ = llcorner.x_ / size_;
1269 metrics_->fontBBoxYMin_ = llcorner.y_ / size_;
1270 metrics_->fontBBoxXMax_ = urcorner.x_ / size_;
1271 metrics_->fontBBoxYMax_ = urcorner.y_ / size_;
1273 else if( strcmp( tag, "UnderlinePosition" ) == 0 )
1275 if( ! IS_NAN( metrics_->horizontalMetrics_->underlinePosition_ ) )
1277 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1279 if( ! ( size_ > 0 ) )
1281 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1283 typedef const Lang::Length ValType;
1284 metrics_->horizontalMetrics_->underlinePosition_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1286 else if( strcmp( tag, "UnderlineThickness" ) == 0 )
1288 if( ! IS_NAN( metrics_->horizontalMetrics_->underlineThickness_ ) )
1290 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1292 if( ! ( size_ > 0 ) )
1294 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1296 typedef const Lang::Length ValType;
1297 metrics_->horizontalMetrics_->underlineThickness_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1299 else if( strcmp( tag, "ItalicAngle" ) == 0 )
1301 if( ! IS_NAN( metrics_->horizontalMetrics_->italicAngleRadians_ ) )
1303 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1305 typedef const Lang::Float ValType;
1306 metrics_->horizontalMetrics_->italicAngleRadians_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1308 else
1310 typedef const Lang::String ValType;
1311 RefCountPtr< ValType > typedVal = Helpers::down_cast< ValType >( val, callLoc );
1312 metrics_->assortedGlobalInfo_.push_back( FontMetrics::AFM::AssortedInfo( tagMem, typedVal->val_ ) );
1316 Kernel::ContRef cont = evalState->cont_;
1317 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
1318 evalState );
1319 return;
1321 catch( const NonLocalExit::NotThisType & ball )
1323 /* Wrong type; never mind!.. but see below!
1327 throw Exceptions::TypeMismatch( callLoc, piece->getTypeName( ), Helpers::typeSetString( Lang::Type3Glyph::staticTypeName( ), Lang::KernedText::staticTypeName( ), Lang::TaggedValue2D::staticTypeName( ) ) );
1330 void
1331 Kernel::WarmType3Font::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1333 if( glyphs_.empty( ) )
1335 throw Exceptions::OutOfRange( callLoc, "A font without glyphs?!" );
1337 if( ! ( size_ > 0 ) )
1339 throw Exceptions::OutOfRange( callLoc, "Missing 'size." );
1341 if( strlen( metrics_->fontName_.getPtr( ) ) == 0 )
1343 throw Exceptions::OutOfRange( callLoc, "Missing 'FontName." );
1345 if( metrics_->weightNumber_ == 0 )
1347 metrics_->weightNumber_ = 400;
1349 bool findBBox = false;
1350 if( metrics_->fontBBoxXMax_ < metrics_->fontBBoxXMin_ )
1352 findBBox = true;
1355 Concrete::ReciprocalLength invSize = 1 / size_;
1357 metrics_->charCount_ = glyphs_.size( );
1358 metrics_->isCIDFont_ = false;
1360 size_t firstChar = INT_MAX;
1361 size_t lastChar = 0;
1363 // In the first scan of the glyphs, only firstChar and lastChar are computed. The other tasks are performed in the later scan.
1364 typedef typeof glyphs_ ListType;
1365 for( ListType::const_iterator i = glyphs_.begin( ); i != glyphs_.end( ); ++i )
1367 size_t code = (*i)->code( );
1368 if( code > 0 )
1370 firstChar = std::min( firstChar, code );
1371 lastChar = std::max( lastChar, code );
1376 RefCountPtr< SimplePDF::PDF_Vector > widths;
1378 RefCountPtr< SimplePDF::PDF_Object > stdWidth = SimplePDF::newFloat( 0 );
1379 widths->vec.resize( lastChar - firstChar + 1, stdWidth );
1381 RefCountPtr< SimplePDF::PDF_Dictionary > charProcs;
1382 RefCountPtr< SimplePDF::PDF_Resources > resources;
1383 // RefCountPtr< SimplePDF::PDF_Stream_out > toUnicode;
1385 RefCountPtr< FontMetrics::WritingDirectionMetrics > horizontal = metrics_->horizontalMetrics_;
1386 horizontal->charData_.reserve( glyphs_.size( ) );
1389 // This is the main loop over all glyphs.
1390 typedef typeof glyphs_ ListType;
1391 for( ListType::const_iterator i = glyphs_.begin( ); i != glyphs_.end( ); ++i )
1393 size_t code = (*i)->code( );
1394 if( code > 0 )
1396 widths->vec[ code - firstChar ] = SimplePDF::newFloat( (*i)->widthX( ) );
1399 RefCountPtr< SimplePDF::PDF_Stream_out > glyphStream;
1400 (*i)->shipout( glyphStream->data, resources );
1401 charProcs->dic[ (*i)->name( ).getPtr( ) ] = SimplePDF::indirect( glyphStream, & Kernel::theIndirectObjectCount );
1403 size_t pos = horizontal->charData_.size( );
1404 FontMetrics::CharacterMetrics * glyphMetrics = new FontMetrics::CharacterMetrics( pos );
1405 (*i)->setupMetric( glyphMetrics, invSize );
1406 horizontal->charData_.push_back( glyphMetrics );
1407 horizontal->nameMap_[ (*i)->name( ) ] = pos;
1408 if( code > 0 )
1410 horizontal->codeMap_[ code ] = pos;
1413 if( findBBox )
1415 (*i)->enlargeBBox( & metrics_->fontBBoxXMin_, & metrics_->fontBBoxYMin_, & metrics_->fontBBoxXMax_, & metrics_->fontBBoxYMax_ );
1420 RefCountPtr< SimplePDF::PDF_Vector > fontBBox( new SimplePDF::PDF_Vector( metrics_->fontBBoxXMin_, metrics_->fontBBoxYMin_,
1421 metrics_->fontBBoxXMax_, metrics_->fontBBoxYMax_ ) );
1422 RefCountPtr< SimplePDF::PDF_Dictionary > fontDescriptor;
1423 (*fontDescriptor)[ "Type" ] = SimplePDF::newName( "FontDescriptor" );
1424 (*fontDescriptor)[ "FontName" ] = SimplePDF::newName( metrics_->fontName_.getPtr( ) );
1425 if( metrics_->familyName_.getPtr( ) != NullPtr< const char >( ) )
1427 (*fontDescriptor)[ "FontFamily" ] = SimplePDF::newName( metrics_->familyName_.getPtr( ) );
1429 if( metrics_->weight_.getPtr( ) != NullPtr< const char >( ) )
1431 // It has already been asserted that this value is legal.
1432 (*fontDescriptor)[ "FontStretch" ] = SimplePDF::newName( metrics_->weight_.getPtr( ) );
1434 if( metrics_->weightNumber_ > 0 )
1436 // It has already been asserted that this value is legal.
1437 (*fontDescriptor)[ "FontWeight" ] = SimplePDF::newInt( metrics_->weightNumber_ );
1439 (*fontDescriptor)[ "Flags" ] = SimplePDF::newInt( (size_t)(1) << ( 6 - 1 ) ); // This is just the "Nonsymbolic" flag.
1440 (*fontDescriptor)[ "FontBBox" ] = fontBBox;
1441 if( ! IS_NAN( horizontal->italicAngleRadians_ ) )
1443 (*fontDescriptor)[ "ItalicAngle" ] = SimplePDF::newFloat( ( 180 / M_PI ) * horizontal->italicAngleRadians_ );
1445 else
1447 throw Exceptions::OutOfRange( callLoc, "Missing 'ItalicAngle." );
1449 if( ! IS_NAN( metrics_->ascender_ ) )
1451 (*fontDescriptor)[ "Ascent" ] = SimplePDF::newFloat( metrics_->ascender_ );
1453 if( ! IS_NAN( metrics_->descender_ ) )
1455 (*fontDescriptor)[ "Descent" ] = SimplePDF::newFloat( metrics_->descender_ );
1457 if( ! IS_NAN( metrics_->leading_ ) )
1459 (*fontDescriptor)[ "Leading" ] = SimplePDF::newFloat( metrics_->leading_ );
1461 if( ! IS_NAN( metrics_->capHeight_ ) )
1463 (*fontDescriptor)[ "CapHeight" ] = SimplePDF::newFloat( metrics_->capHeight_ );
1465 if( ! IS_NAN( metrics_->xHeight_ ) )
1467 (*fontDescriptor)[ "XHeight" ] = SimplePDF::newFloat( metrics_->xHeight_ );
1469 if( ! IS_NAN( metrics_->stdHW_ ) )
1471 (*fontDescriptor)[ "StemH" ] = SimplePDF::newFloat( metrics_->stdHW_ );
1473 if( ! IS_NAN( metrics_->stdVW_ ) )
1475 (*fontDescriptor)[ "StemV" ] = SimplePDF::newFloat( metrics_->stdVW_ );
1478 Concrete::Length the1bp( 1 );
1480 RefCountPtr< SimplePDF::PDF_Dictionary > dic;
1481 RefCountPtr< SimplePDF::PDF_Object > indirection = SimplePDF::indirect( dic, & Kernel::theIndirectObjectCount );
1482 (*dic)[ "Type" ] = SimplePDF::newName( "Font" );
1483 (*dic)[ "Subtype" ] = SimplePDF::newName( "Type3" );
1484 (*dic)[ "Encoding" ] = SimplePDF::newName( "MacRomanEncoding" );
1485 (*dic)[ "FontBBox" ] = fontBBox;
1486 (*dic)[ "FontMatrix" ] = RefCountPtr< SimplePDF::PDF_Vector >( new SimplePDF::PDF_Vector( the1bp * invSize, 0, 0, the1bp * invSize, 0, 0 ) );
1487 (*dic)[ "CharProcs" ] = charProcs;
1488 (*dic)[ "FirstChar" ] = SimplePDF::newInt( firstChar );
1489 (*dic)[ "LastChar" ] = SimplePDF::newInt( lastChar );
1490 (*dic)[ "Widths" ] = widths;
1491 (*dic)[ "FontDescriptor" ] = fontDescriptor;
1492 (*dic)[ "Resources" ] = SimplePDF::indirect( resources, & Kernel::theIndirectObjectCount );
1494 // {
1495 // static bool shown = false;
1496 // if( ! shown )
1497 // {
1498 // std::cerr << "Warning: The ToUnicode CMap is not setup by Shapes." << std::endl ;
1499 // shown = true;
1500 // }
1501 // }
1502 // (*dic)[ "ToUnicode" ] = toUnicode;
1504 Kernel::ContRef cont = evalState->cont_;
1505 cont->takeValue( Kernel::ValueRef( new Lang::Font( metrics_->fontName_,
1506 indirection,
1507 metrics_ ) ),
1508 evalState );
1511 void
1512 Kernel::WarmType3Font::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1514 throw Exceptions::MiscellaneousRequirement( strrefdup( "A type 3 font state cannot be peeked." ) );
1517 void
1518 Kernel::WarmType3Font::gcMark( Kernel::GCMarkedSet & marked )
1521 typedef typeof kernings_ ListType;
1522 for( ListType::const_iterator i = kernings_.begin( ); i != kernings_.end( ); ++i )
1524 const_cast< Lang::KernedText * >( i->getPtr( ) )->gcMark( marked );
1528 typedef typeof glyphs_ ListType;
1529 for( ListType::const_iterator i = glyphs_.begin( ); i != glyphs_.end( ); ++i )
1531 const_cast< Lang::Type3Glyph * >( i->getPtr( ) )->gcMark( marked );
1537 void
1538 Kernel::WarmType3Font::initializeLegalStrechValues( std::set< const char *, charPtrLess > * legalStretchValues )
1540 legalStretchValues->insert( "UltraCondensed" );
1541 legalStretchValues->insert( "ExtraCondensed" );
1542 legalStretchValues->insert( "Condensed" );
1543 legalStretchValues->insert( "SemiCondensed" );
1544 legalStretchValues->insert( "Normal" );
1545 legalStretchValues->insert( "SemiExpanded" );
1546 legalStretchValues->insert( "Expanded" );
1547 legalStretchValues->insert( "ExtraExpanded" );
1548 legalStretchValues->insert( "UltraExpanded" );
1552 Kernel::WarmRandomDevice::WarmRandomDevice( const char * deviceName )
1553 : deviceName_( deviceName )
1556 Kernel::WarmRandomDevice::~WarmRandomDevice( )
1559 RefCountPtr< const Lang::Class > Kernel::WarmRandomDevice::TypeID( new Lang::SystemFinalClass( strrefdup( "#RandomDevice" ) ) );
1560 TYPEINFOIMPL_STATE( WarmRandomDevice );
1562 void
1563 Kernel::WarmRandomDevice::read( char * dst, size_t sz )
1565 if( ! idev_.is_open( ) )
1567 idev_.open( deviceName_ );
1568 if( ! idev_.is_open( ) || ! idev_.good( ) )
1570 throw Exceptions::ExternalError( strrefdup( deviceName_ + std::string( " could not be opened for input." ) ) );
1574 idev_.read( dst, sz );
1577 void
1578 Kernel::WarmRandomDevice::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
1580 if( ! odev_.is_open( ) )
1582 odev_.open( deviceName_ );
1583 if( ! odev_.is_open( ) || ! odev_.good( ) )
1585 throw Exceptions::ExternalError( strrefdup( deviceName_ + std::string( " could not be opened for output." ) ) );
1589 piece->show( odev_ );
1590 Kernel::ContRef cont = evalState->cont_;
1591 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
1592 evalState );
1595 void
1596 Kernel::WarmRandomDevice::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1598 throw Exceptions::MiscellaneousRequirement( strrefdup( "The random device cannot be frozen." ) );
1601 void
1602 Kernel::WarmRandomDevice::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1604 if( ! idev_.is_open( ) )
1606 idev_.open( deviceName_ );
1607 if( ! idev_.is_open( ) || ! idev_.good( ) )
1609 throw Exceptions::ExternalError( strrefdup( deviceName_ + std::string( " could not be opened for output." ) ) );
1613 unsigned char tmp;
1614 idev_.read( reinterpret_cast< char * >( & tmp ), 1 );
1615 Kernel::ContRef cont = evalState->cont_;
1616 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::Integer( tmp ) ),
1617 evalState );
1620 void
1621 Kernel::WarmRandomDevice::gcMark( Kernel::GCMarkedSet & marked )
1625 Kernel::WarmTime::WarmTime( )
1628 Kernel::WarmTime::~WarmTime( )
1631 RefCountPtr< const Lang::Class > Kernel::WarmTime::TypeID( new Lang::SystemFinalClass( strrefdup( "#Time" ) ) );
1632 TYPEINFOIMPL_STATE( WarmTime );
1634 void
1635 Kernel::WarmTime::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
1637 throw Exceptions::MiscellaneousRequirement( strrefdup( "The time does not accept values." ) );
1640 void
1641 Kernel::WarmTime::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1643 throw Exceptions::MiscellaneousRequirement( strrefdup( "The time cannot be frozen." ) );
1646 void
1647 Kernel::WarmTime::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1649 time_t t = time( 0 );
1650 Kernel::ContRef cont = evalState->cont_;
1651 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::ChronologicalTime( t ) ),
1652 evalState );
1655 void
1656 Kernel::WarmTime::gcMark( Kernel::GCMarkedSet & marked )
1660 Kernel::WarmRandomState::WarmRandomState( char * state )
1661 : state_( state )
1664 Kernel::WarmRandomState::~WarmRandomState( )
1666 delete state_; // Let's hope this is not in use!
1669 RefCountPtr< const Lang::Class > Kernel::WarmRandomState::TypeID( new Lang::SystemFinalClass( strrefdup( "#RandomState" ) ) );
1670 TYPEINFOIMPL_STATE( WarmRandomState );
1672 void
1673 Kernel::WarmRandomState::setState( )
1675 setstate( state_ );
1678 void
1679 Kernel::WarmRandomState::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
1681 throw Exceptions::MiscellaneousRequirement( strrefdup( "A random state does not accept values." ) );
1684 void
1685 Kernel::WarmRandomState::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1687 throw Exceptions::MiscellaneousRequirement( strrefdup( "A random state cannot be frozen." ) );
1690 void
1691 Kernel::WarmRandomState::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1693 setState( );
1694 long tmp = random( );
1695 Kernel::ContRef cont = evalState->cont_;
1696 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::Integer( tmp ) ),
1697 evalState );
1700 void
1701 Kernel::WarmRandomState::gcMark( Kernel::GCMarkedSet & marked )
1705 Kernel::WarmColorInterpolator::WarmColorInterpolator( )
1706 : hasKey_( false ), colorType_( Lang::ColorInterpolator::UNDEFINED )
1709 Kernel::WarmColorInterpolator::~WarmColorInterpolator( )
1712 RefCountPtr< const Lang::Class > Kernel::WarmColorInterpolator::TypeID( new Lang::SystemFinalClass( strrefdup( "#ColorInterpolator" ) ) );
1713 TYPEINFOIMPL_STATE( WarmColorInterpolator );
1715 void
1716 Kernel::WarmColorInterpolator::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Kernel::PassedDyn & dyn, const Ast::SourceLocation & callLoc )
1718 if( hasKey_ )
1720 switch( colorType_ )
1722 case Lang::ColorInterpolator::UNDEFINED:
1725 RGBcolor_->push_back( Helpers::down_cast< const Lang::RGB >( piece, callLoc )->components( ) );
1726 colorType_ = Lang::ColorInterpolator::RGB;
1727 break;
1729 catch( const Exceptions::TypeMismatch & )
1734 graycolor_->push_back( Helpers::down_cast< const Lang::Gray >( piece, callLoc )->components( ) );
1735 colorType_ = Lang::ColorInterpolator::GRAY;
1736 break;
1738 catch( const Exceptions::TypeMismatch & )
1743 CMYKcolor_->push_back( Helpers::down_cast< const Lang::CMYK >( piece, callLoc )->components( ) );
1744 colorType_ = Lang::ColorInterpolator::CMYK;
1745 break;
1747 catch( const Exceptions::TypeMismatch & )
1749 throw Exceptions::MiscellaneousRequirement( strrefdup( "Only colors can be passed to an interpolator." ) );
1751 case Lang::ColorInterpolator::RGB:
1752 RGBcolor_->push_back( Helpers::down_cast< const Lang::RGB >( piece, callLoc )->components( ) );
1753 break;
1755 case Lang::ColorInterpolator::GRAY:
1756 graycolor_->push_back( Helpers::down_cast< const Lang::Gray >( piece, callLoc )->components( ) );
1757 break;
1759 case Lang::ColorInterpolator::CMYK:
1760 CMYKcolor_->push_back( Helpers::down_cast< const Lang::CMYK >( piece, callLoc )->components( ) );
1761 break;
1764 else
1766 typedef const Lang::Float ArgType;
1767 double key = Helpers::down_cast< ArgType >( piece, callLoc )->val_;
1768 if( !key_->empty( ) && key < key_->back( ) )
1770 throw Exceptions::MiscellaneousRequirement( strrefdup( "Keys must be added in nondecreasing order to an interpolator." ) );
1772 else
1774 key_->push_back( key );
1778 hasKey_ = ! hasKey_;
1780 Kernel::ContRef cont = evalState->cont_;
1781 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
1782 evalState );
1785 void
1786 Kernel::WarmColorInterpolator::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1788 if( key_->empty( ) )
1790 throw Exceptions::MiscellaneousRequirement( strrefdup( "There are no colors that define the interpolation." ) );
1792 if( hasKey_ )
1794 throw Exceptions::MiscellaneousRequirement( strrefdup( "Missing color for the last key." ) );
1797 Kernel::ContRef cont = evalState->cont_;
1798 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::ColorInterpolator( key_, RGBcolor_, graycolor_, CMYKcolor_, colorType_ ) ),
1799 evalState );
1802 void
1803 Kernel::WarmColorInterpolator::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1805 throw Exceptions::MiscellaneousRequirement( strrefdup( "An interpolator cannot be peeked." ) );
1808 void
1809 Kernel::WarmColorInterpolator::gcMark( Kernel::GCMarkedSet & marked )
1814 void
1815 Kernel::registerHot( Kernel::Environment * env )
1817 env->initDefine( Lang::CANVAS_ID, new Kernel::WarmGroup2D );
1818 env->initDefine( Lang::CATALOG_ID, new Kernel::WarmCatalog );
1819 env->initDefine( "stdout", new Kernel::WarmOstream( std::cout ) );
1820 env->initDefine( "stderr", new Kernel::WarmOstream( std::cerr ) );
1821 env->initDefine( "randomdevice", new Kernel::WarmRandomDevice( "/dev/urandom" ) );
1822 env->initDefine( "time", new Kernel::WarmTime );
1823 env->initDefine( "ignore", new Kernel::WarmIgnore );
1825 env->initDefine( "newIgnore", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmIgnore > ) );
1826 env->initDefine( "newGroup", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmGroup2D > ) );
1827 env->initDefine( "newGroup3D", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmGroup3D > ) );
1828 env->initDefine( "newZBuf", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmZBuf > ) );
1829 env->initDefine( "newZSorter", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmZSorter > ) );
1830 env->initDefine( "newString", Kernel::ValueRef( new Lang::HotDefault< Kernel::Warm_ostringstream > ) );
1831 env->initDefine( "newLights", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmGroupLights > ) );
1832 env->initDefine( "newTimer", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmTimer > ) );
1833 env->initDefine( "newText", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmText > ) );
1834 env->initDefine( "newFont", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmType3Font > ) );
1835 env->initDefine( "newColorInterpolator", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmColorInterpolator > ) );