Update procedures
[shapes.git] / source / hottypes.cc
blob105147a07cd91bc210f4caa94af58d5685dc7e4d
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, 2013 Henrik Tidefelt
19 #include "Shapes_Helpers_decls.h"
21 #include "hottypes.h"
22 #include "globals.h"
23 #include "continuations.h"
24 #include "texttypes.h"
25 #include "fontmetrics.h"
26 #include "tagtypes.h"
27 #include "isnan.h"
28 #include "pdfstructure.h"
29 #include "timetypes.h"
30 #include "shapescore.h"
31 #include "warn.h"
33 #include <sstream>
34 #include <limits>
35 #include <sys/resource.h>
36 #include <cstdlib>
37 #include <cstring>
39 using namespace Shapes;
42 Lang::HotTriple::HotTriple( const RefCountPtr< const Lang::Value > & init, RefCountPtr< const Lang::Function > update, RefCountPtr< const Lang::Function > result )
43 : init_( init ), update_( update ), result_( result )
44 { }
46 Lang::HotTriple::~HotTriple( )
47 { }
49 Kernel::State *
50 Lang::HotTriple::newState( ) const
52 return new Kernel::WarmTriple( init_, update_, result_ );
55 void
56 Lang::HotTriple::gcMark( Kernel::GCMarkedSet & marked )
58 const_cast< Lang::Value * >( init_.getPtr( ) )->gcMark( marked );
59 const_cast< Lang::Function * >( update_.getPtr( ) )->gcMark( marked );
60 const_cast< Lang::Function * >( result_.getPtr( ) )->gcMark( marked );
65 Lang::HotRandomSeed::HotRandomSeed( size_t sz, Kernel::WarmRandomDevice * dev )
66 : sz_( sz ), state_( new char[ sz ] )
68 char * oldState = initstate( 1, state_, sz_ );
69 dev->read( state_, sz_ );
70 setstate( oldState );
73 Lang::HotRandomSeed::HotRandomSeed( size_t sz, unsigned long seed )
74 : sz_( sz ), state_( new char[ sz ] )
76 char * oldState = initstate( seed, state_, sz_ );
77 setstate( oldState );
80 Lang::HotRandomSeed::~HotRandomSeed( )
82 delete state_;
85 Kernel::State *
86 Lang::HotRandomSeed::newState( ) const
88 char * stateCopy = new char[ sz_ ];
89 memcpy( stateCopy, state_, sz_ );
90 return new Kernel::WarmRandomState( stateCopy ); // This handles ownership to the new state.
93 void
94 Lang::HotRandomSeed::gcMark( Kernel::GCMarkedSet & marked )
95 { }
100 Kernel::WarmTriple::WarmTriple( const RefCountPtr< const Lang::Value > & pile, RefCountPtr< const Lang::Function > update, RefCountPtr< const Lang::Function > result )
101 : pile_( pile ), update_( update ), result_( result )
104 Kernel::WarmTriple::~WarmTriple( )
107 RefCountPtr< const Lang::Class > Kernel::WarmTriple::TypeID( new Lang::SystemFinalClass( strrefdup( "#UserState" ) ) );
108 TYPEINFOIMPL_STATE( WarmTriple );
110 void
111 Kernel::WarmTriple::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
113 /* This seems dangerous. I have not verified that pile will still exist when the continuation below is invoked.
115 evalState->cont_ = Kernel::ContRef( new Kernel::StmtStoreValueContinuation( & pile_,
116 evalState->cont_,
117 callLoc ) );
118 update_->call( evalState, pile_, piece, callLoc );
121 void
122 Kernel::WarmTriple::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
124 /* The right continuation is set by the calling variable.
126 result_->call( evalState, pile_, callLoc );
129 void
130 Kernel::WarmTriple::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
132 /* The right continuation is set by the calling variable.
134 result_->call( evalState, pile_, callLoc );
137 void
138 Kernel::WarmTriple::gcMark( Kernel::GCMarkedSet & marked )
140 const_cast< Lang::Value * >( pile_.getPtr( ) )->gcMark( marked );
141 const_cast< Lang::Function * >( update_.getPtr( ) )->gcMark( marked );
142 const_cast< Lang::Function * >( result_.getPtr( ) )->gcMark( marked );
146 Kernel::WarmIgnore::WarmIgnore( )
149 Kernel::WarmIgnore::~WarmIgnore( )
152 RefCountPtr< const Lang::Class > Kernel::WarmIgnore::TypeID( new Lang::SystemFinalClass( strrefdup( "#Ignore" ) ) );
153 TYPEINFOIMPL_STATE( WarmIgnore );
155 void
156 Kernel::WarmIgnore::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
158 /* Ignore piece! */
160 Kernel::ContRef cont = evalState->cont_;
161 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
162 evalState );
165 void
166 Kernel::WarmIgnore::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
168 throw Exceptions::MiscellaneousRequirement( strrefdup( "An ignore state cannot be frozen." ) );
171 void
172 Kernel::WarmIgnore::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
174 throw Exceptions::MiscellaneousRequirement( strrefdup( "An ignore state cannot be peeked." ) );
177 void
178 Kernel::WarmIgnore::gcMark( Kernel::GCMarkedSet & marked )
182 Kernel::WarmOstream::WarmOstream( std::ostream & os )
183 : os_( os )
186 Kernel::WarmOstream::~WarmOstream( )
189 RefCountPtr< const Lang::Class > Kernel::WarmOstream::TypeID( new Lang::SystemFinalClass( strrefdup( "#OutputStream" ) ) );
190 TYPEINFOIMPL_STATE( WarmOstream );
192 void
193 Kernel::WarmOstream::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
195 piece->show( os_ );
196 Kernel::ContRef cont = evalState->cont_;
197 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
198 evalState );
201 void
202 Kernel::WarmOstream::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
204 throw Exceptions::MiscellaneousRequirement( strrefdup( "A warm ostream cannot be frozen." ) );
207 void
208 Kernel::WarmOstream::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
210 throw Exceptions::MiscellaneousRequirement( strrefdup( "A warm ostream cannot be peeked." ) );
213 void
214 Kernel::WarmOstream::gcMark( Kernel::GCMarkedSet & marked )
218 Kernel::Warm_ostringstream::Warm_ostringstream( )
221 Kernel::Warm_ostringstream::~Warm_ostringstream( )
224 RefCountPtr< const Lang::Class > Kernel::Warm_ostringstream::TypeID( new Lang::SystemFinalClass( strrefdup( "#StringConcatenator" ) ) );
225 TYPEINFOIMPL_STATE( Warm_ostringstream );
227 void
228 Kernel::Warm_ostringstream::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
230 piece->show( os_ );
231 Kernel::ContRef cont = evalState->cont_;
232 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
233 evalState );
236 void
237 Kernel::Warm_ostringstream::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
239 Kernel::ContRef cont = evalState->cont_;
240 cont->takeValue( Kernel::ValueRef( new Lang::String( strrefdup( os_.str( ).c_str( ) ) ) ),
241 evalState );
244 void
245 Kernel::Warm_ostringstream::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
247 Kernel::ContRef cont = evalState->cont_;
248 cont->takeValue( Kernel::ValueRef( new Lang::String( strrefdup( os_.str( ).c_str( ) ) ) ),
249 evalState );
252 void
253 Kernel::Warm_ostringstream::gcMark( Kernel::GCMarkedSet & marked )
256 namespace Shapes
258 namespace Kernel
261 template< class T >
262 class Mutator_erase : public Lang::CoreMutator
264 public:
265 Mutator_erase( const char * name )
266 : CoreMutator( name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
269 virtual void
270 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
272 args.applyDefaults( callLoc );
274 typedef T StateType;
275 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
276 state->erase( );
278 Kernel::ContRef cont = evalState->cont_;
279 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
280 evalState );
284 template< class T >
285 class Mutator_remove : public Lang::CoreMutator
287 public:
288 Mutator_remove( const char * name )
289 : CoreMutator( name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
291 formals_->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE );
293 virtual void
294 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
296 args.applyDefaults( callLoc );
298 typedef T StateType;
299 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
301 typedef const Lang::Symbol KeyType;
302 RefCountPtr< KeyType > key = Helpers::down_cast_MutatorArgument< KeyType >( state, name_, args, 0, callLoc );
304 state->remove( key->getKey( ) );
306 Kernel::ContRef cont = evalState->cont_;
307 cont->takeValue( Lang::THE_VOID,
308 evalState );
316 Kernel::WarmGroup2D::WarmGroup2D( )
317 : pile_( Lang::THE_NULL2D )
320 Kernel::WarmGroup2D::~WarmGroup2D( )
323 void
324 WarmGroup2D_register_mutators( Lang::SystemFinalClass * dstClass )
326 dstClass->registerMutator( new Kernel::Mutator_erase< Kernel::WarmGroup2D >( "erase" ) );
327 dstClass->registerMutator( new Kernel::Mutator_remove< Kernel::WarmGroup2D >( "remove" ) );
330 RefCountPtr< const Lang::Class > Kernel::WarmGroup2D::TypeID( new Lang::SystemFinalClass( strrefdup( "#Group2D" ), WarmGroup2D_register_mutators ) );
331 TYPEINFOIMPL_STATE( WarmGroup2D );
334 void
335 Kernel::WarmGroup2D::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
337 typedef const Lang::Drawable2D ArgType;
338 RefCountPtr< ArgType > arg = Helpers::down_cast< ArgType >( piece, callLoc );
341 /* For objects of user-defined type, we also check that the class inherits from Drawable.
343 typedef const Lang::Instance UserType;
344 UserType * obj = dynamic_cast< UserType * >( arg.getPtr( ) );
345 if( obj != 0 )
347 if( ! obj->getClass( )->method_isa( Lang::Drawable2D::TypeID ) )
349 throw Exceptions::TypeMismatch( callLoc, "2D insertion", piece->getTypeName( ), ArgType::staticTypeName( ) );
354 pile_ = RefCountPtr< const Lang::Group2D >( new Lang::GroupPair2D( arg,
355 pile_,
356 evalState->dyn_->getGraphicsState( ) ) );
357 Kernel::ContRef cont = evalState->cont_;
358 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
359 evalState );
362 void
363 Kernel::WarmGroup2D::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
365 Kernel::ContRef cont = evalState->cont_;
366 cont->takeValue( pile_,
367 evalState );
370 void
371 Kernel::WarmGroup2D::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
373 Kernel::ContRef cont = evalState->cont_;
374 cont->takeValue( pile_,
375 evalState );
378 void
379 Kernel::WarmGroup2D::erase( )
381 pile_ = Lang::THE_NULL2D;
384 void
385 Kernel::WarmGroup2D::remove( Lang::Symbol::KeyType key )
387 pile_ = pile_->removeShallow( key );
390 void
391 Kernel::WarmGroup2D::gcMark( Kernel::GCMarkedSet & marked )
393 const_cast< Lang::Group2D * >( pile_.getPtr( ) )->gcMark( marked );
398 Kernel::WarmGroup3D::WarmGroup3D( )
399 : pile_( Lang::THE_NULL3D )
402 Kernel::WarmGroup3D::~WarmGroup3D( )
405 void
406 WarmGroup3D_register_mutators( Lang::SystemFinalClass * dstClass )
408 dstClass->registerMutator( new Kernel::Mutator_erase< Kernel::WarmGroup3D >( "erase" ) );
409 dstClass->registerMutator( new Kernel::Mutator_remove< Kernel::WarmGroup3D >( "remove" ) );
412 RefCountPtr< const Lang::Class > Kernel::WarmGroup3D::TypeID( new Lang::SystemFinalClass( strrefdup( "#Group3D" ), WarmGroup3D_register_mutators ) );
413 TYPEINFOIMPL_STATE( WarmGroup3D );
415 void
416 Kernel::WarmGroup3D::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
418 pile_ = RefCountPtr< const Lang::Group3D >( new Lang::GroupPair3D( Helpers::down_cast< const Lang::Drawable3D >( piece, callLoc ),
419 pile_,
420 evalState->dyn_->getGraphicsState( ) ) );
421 Kernel::ContRef cont = evalState->cont_;
422 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
423 evalState );
426 void
427 Kernel::WarmGroup3D::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
429 Kernel::ContRef cont = evalState->cont_;
430 cont->takeValue( pile_,
431 evalState );
434 void
435 Kernel::WarmGroup3D::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
437 Kernel::ContRef cont = evalState->cont_;
438 cont->takeValue( pile_,
439 evalState );
442 void
443 Kernel::WarmGroup3D::erase( )
445 pile_ = Lang::THE_NULL3D;
448 void
449 Kernel::WarmGroup3D::remove( Lang::Symbol::KeyType key )
451 pile_ = pile_->removeShallow( key );
454 void
455 Kernel::WarmGroup3D::gcMark( Kernel::GCMarkedSet & marked )
457 const_cast< Lang::Group3D * >( pile_.getPtr( ) )->gcMark( marked );
461 Kernel::WarmGroupLights::WarmGroupLights( )
462 : pile_( Lang::THE_NULL_LIGHTS )
465 Kernel::WarmGroupLights::~WarmGroupLights( )
468 RefCountPtr< const Lang::Class > Kernel::WarmGroupLights::TypeID( new Lang::SystemFinalClass( strrefdup( "#GroupLights" ) ) );
469 TYPEINFOIMPL_STATE( WarmGroupLights );
471 void
472 Kernel::WarmGroupLights::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
474 pile_ = RefCountPtr< const Lang::LightGroup >( new Lang::LightPair( Helpers::down_cast< const Lang::LightSource >( piece, callLoc ),
475 pile_ ) );
476 Kernel::ContRef cont = evalState->cont_;
477 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
478 evalState );
481 void
482 Kernel::WarmGroupLights::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
484 Kernel::ContRef cont = evalState->cont_;
485 cont->takeValue( pile_,
486 evalState );
489 void
490 Kernel::WarmGroupLights::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
492 Kernel::ContRef cont = evalState->cont_;
493 cont->takeValue( pile_,
494 evalState );
497 void
498 Kernel::WarmGroupLights::gcMark( Kernel::GCMarkedSet & marked )
500 const_cast< Lang::LightGroup * >( pile_.getPtr( ) )->gcMark( marked );
504 Kernel::WarmZBuf::WarmZBuf( )
507 Kernel::WarmZBuf::~WarmZBuf( )
510 RefCountPtr< const Lang::Class > Kernel::WarmZBuf::TypeID( new Lang::SystemFinalClass( strrefdup( "#ZBuf" ) ) );
511 TYPEINFOIMPL_STATE( WarmZBuf );
513 void
514 Kernel::WarmZBuf::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
518 typedef const Lang::Drawable3D ArgType;
519 RefCountPtr< ArgType > drawable = Helpers::try_cast_CoreArgument< ArgType >( piece );
522 drawable->polygonize( pile_.getPtr( ), strokePile_.getPtr( ), evalState->dyn_, Lang::THE_3D_IDENTITY, drawable );
524 catch( const char * ball )
526 std::ostringstream oss;
527 oss << "Conversion to polygon failed with: " << ball ;
528 throw Exceptions::OutOfRange( callLoc, strrefdup( oss ) );
530 Kernel::ContRef cont = evalState->cont_;
531 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
532 evalState );
533 return;
535 catch( const NonLocalExit::NotThisType & ball )
537 /* Wrong type; never mind!.. but see below!
543 lightPile_->push_back( Helpers::try_cast_CoreArgument< const Lang::LightSource >( piece ) );
544 Kernel::ContRef cont = evalState->cont_;
545 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
546 evalState );
547 return;
549 catch( const NonLocalExit::NotThisType & ball )
551 /* Wrong type; never mind!.. but see below!
557 typedef const Lang::LightGroup ArgType;
558 RefCountPtr< ArgType > lights = Helpers::try_cast_CoreArgument< ArgType >( piece );
560 while( ! lights->isNull( ) )
562 typedef const Lang::LightPair PairType;
563 RefCountPtr< PairType > p = lights.down_cast< PairType >( );
564 lightPile_->push_back( p->car( ) );
565 lights = p->cdr( );
568 Kernel::ContRef cont = evalState->cont_;
569 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
570 evalState );
571 return;
573 catch( const NonLocalExit::NotThisType & ball )
575 /* Wrong type; never mind!.. but see below!
579 throw Exceptions::TypeMismatch( callLoc, piece->getTypeName( ), Helpers::typeSetString( Lang::Drawable3D::staticTypeName( ), Lang::LightSource::staticTypeName( ) ) );
582 void
583 Kernel::WarmZBuf::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
585 Kernel::ContRef cont = evalState->cont_;
586 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::ZBuf( pile_, strokePile_, lightPile_, evalState->dyn_->getGraphicsState( ) ) ),
587 evalState );
590 void
591 Kernel::WarmZBuf::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
593 throw Exceptions::MiscellaneousRequirement( strrefdup( "A z-buffer state cannot be peeked." ) );
596 void
597 Kernel::WarmZBuf::gcMark( Kernel::GCMarkedSet & marked )
600 typedef typeof *pile_ ListType;
601 for( ListType::const_iterator i = pile_->begin( ); i != pile_->end( ); ++i )
603 const_cast< Computation::PaintedPolygon3D * >( i->getPtr( ) )->gcMark( marked );
606 // {
607 // typedef typeof *strokePile_ ListType;
608 // for( ListType::const_iterator i = strokePile_->begin( ); i != strokePile_->end( ); ++i )
609 // {
610 // const_cast< Computation::StrokedLine3D * >( i->getPtr( ) )->gcMark( marked );
611 // }
612 // }
614 typedef typeof *lightPile_ ListType;
615 for( ListType::const_iterator i = lightPile_->begin( ); i != lightPile_->end( ); ++i )
617 const_cast< Lang::LightSource * >( i->getPtr( ) )->gcMark( marked );
623 Kernel::WarmZSorter::WarmZSorter( )
626 Kernel::WarmZSorter::~WarmZSorter( )
629 RefCountPtr< const Lang::Class > Kernel::WarmZSorter::TypeID( new Lang::SystemFinalClass( strrefdup( "#ZSorter" ) ) );
630 TYPEINFOIMPL_STATE( WarmZSorter );
632 void
633 Kernel::WarmZSorter::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
637 typedef const Lang::Drawable3D ArgType;
638 RefCountPtr< ArgType > drawable = Helpers::try_cast_CoreArgument< ArgType >( piece );
641 drawable->polygonize( pile_.getPtr( ), strokePile_.getPtr( ), evalState->dyn_, Lang::THE_3D_IDENTITY, drawable );
643 catch( const char * ball )
645 std::ostringstream oss;
646 oss << "Conversion to polygon failed with: " << ball ;
647 throw Exceptions::OutOfRange( callLoc, strrefdup( oss ) );
649 Kernel::ContRef cont = evalState->cont_;
650 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
651 evalState );
652 return;
654 catch( const NonLocalExit::NotThisType & ball )
656 /* Wrong type; never mind!.. but see below!
662 lightPile_->push_back( Helpers::try_cast_CoreArgument< const Lang::LightSource >( piece ) );
663 Kernel::ContRef cont = evalState->cont_;
664 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
665 evalState );
666 return;
668 catch( const NonLocalExit::NotThisType & ball )
670 /* Wrong type; never mind!.. but see below!
676 typedef const Lang::LightGroup ArgType;
677 RefCountPtr< ArgType > lights = Helpers::try_cast_CoreArgument< ArgType >( piece );
679 while( ! lights->isNull( ) )
681 typedef const Lang::LightPair PairType;
682 RefCountPtr< PairType > p = lights.down_cast< PairType >( );
683 lightPile_->push_back( p->car( ) );
684 lights = p->cdr( );
687 Kernel::ContRef cont = evalState->cont_;
688 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
689 evalState );
690 return;
692 catch( const NonLocalExit::NotThisType & ball )
694 /* Wrong type; never mind!.. but see below!
698 throw Exceptions::TypeMismatch( callLoc, piece->getTypeName( ), Helpers::typeSetString( Lang::Drawable3D::staticTypeName( ), Lang::LightSource::staticTypeName( ) ) );
701 void
702 Kernel::WarmZSorter::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
704 Kernel::ContRef cont = evalState->cont_;
705 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::ZSorter( pile_, strokePile_, lightPile_, evalState->dyn_->getGraphicsState( ) ) ),
706 evalState );
709 void
710 Kernel::WarmZSorter::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
712 throw Exceptions::MiscellaneousRequirement( strrefdup( "A z-sorter state cannot be peeked." ) );
715 void
716 Kernel::WarmZSorter::gcMark( Kernel::GCMarkedSet & marked )
719 typedef typeof *pile_ ListType;
720 for( ListType::const_iterator i = pile_->begin( ); i != pile_->end( ); ++i )
722 const_cast< Computation::PaintedPolygon3D * >( i->getPtr( ) )->gcMark( marked );
725 // {
726 // typedef typeof *strokePile_ ListType;
727 // for( ListType::const_iterator i = strokePile_->begin( ); i != strokePile_->end( ); ++i )
728 // {
729 // const_cast< Computation::StrokedLine3D * >( i->getPtr( ) )->gcMark( marked );
730 // }
731 // }
733 typedef typeof *lightPile_ ListType;
734 for( ListType::const_iterator i = lightPile_->begin( ); i != lightPile_->end( ); ++i )
736 const_cast< Lang::LightSource * >( i->getPtr( ) )->gcMark( marked );
742 Kernel::WarmTimer::WarmTimer( )
744 rusage ru;
745 int res = getrusage( RUSAGE_SELF, &ru );
746 if( res != 0 )
748 throw Exceptions::InternalError( strrefdup( "getrusage failed." ) );
750 start_ = ru.ru_utime;
753 Kernel::WarmTimer::~WarmTimer( )
756 RefCountPtr< const Lang::Class > Kernel::WarmTimer::TypeID( new Lang::SystemFinalClass( strrefdup( "#Timer" ) ) );
757 TYPEINFOIMPL_STATE( WarmTimer );
759 void
760 Kernel::WarmTimer::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
762 throw Exceptions::MiscellaneousRequirement( strrefdup( "A warm timer does not accept values. Please freeze to obtain the number of seconds since creation." ) );
765 void
766 Kernel::WarmTimer::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
768 rusage ru;
769 int res = getrusage( RUSAGE_SELF, &ru );
770 if( res != 0 )
772 throw Exceptions::InternalError( strrefdup( "getrusage failed." ) );
774 timeval stop = ru.ru_utime;
775 double time1 = start_.tv_usec / 1000000.0 + start_.tv_sec;
776 double time2 = stop.tv_usec / 1000000.0 + stop.tv_sec;
778 Kernel::ContRef cont = evalState->cont_;
779 cont->takeValue( Kernel::ValueRef( new Lang::Float( time2 - time1 ) ),
780 evalState );
783 void
784 Kernel::WarmTimer::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
786 rusage ru;
787 int res = getrusage( RUSAGE_SELF, &ru );
788 if( res != 0 )
790 throw Exceptions::InternalError( strrefdup( "grtrusage failed." ) );
792 timeval stop = ru.ru_utime;
793 double time1 = start_.tv_usec / 1000000.0 + start_.tv_sec;
794 double time2 = stop.tv_usec / 1000000.0 + stop.tv_sec;
796 Kernel::ContRef cont = evalState->cont_;
797 cont->takeValue( Kernel::ValueRef( new Lang::Float( time2 - time1 ) ),
798 evalState );
801 void
802 Kernel::WarmTimer::gcMark( Kernel::GCMarkedSet & marked )
806 Kernel::WarmText::WarmText( )
809 Kernel::WarmText::~WarmText( )
812 RefCountPtr< const Lang::Class > Kernel::WarmText::TypeID( new Lang::SystemFinalClass( strrefdup( "#Text" ) ) );
813 TYPEINFOIMPL_STATE( WarmText );
815 void
816 Kernel::WarmText::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
820 typedef const Lang::TextOperation ArgType;
821 pile_->push_back( Helpers::try_cast_CoreArgument< ArgType >( piece ) );
822 Kernel::ContRef cont = evalState->cont_;
823 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
824 evalState );
825 return;
827 catch( const NonLocalExit::NotThisType & ball )
829 /* Wrong type; never mind!.. but see below!
835 typedef const Lang::String ArgType;
836 RefCountPtr< ArgType > str = Helpers::try_cast_CoreArgument< ArgType >( piece );
837 Lang::KernedText * text = new Lang::KernedText( evalState->dyn_->getTextState( ), evalState->dyn_->getGraphicsState( ) );
838 text->pushString( str );
839 pile_->push_back( RefCountPtr< const Lang::TextOperation >( text ) );
840 Kernel::ContRef cont = evalState->cont_;
841 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
842 evalState );
843 return;
845 catch( const NonLocalExit::NotThisType & ball )
847 /* Wrong type; never mind!.. but see below!
853 typedef const Lang::Transform2D ArgType;
854 RefCountPtr< ArgType > tf = Helpers::try_cast_CoreArgument< ArgType >( piece );
855 pile_->push_back( RefCountPtr< const Lang::TextOperation >( new Lang::TextMoveto( tf ) ) );
856 Kernel::ContRef cont = evalState->cont_;
857 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
858 evalState );
859 return;
861 catch( const NonLocalExit::NotThisType & ball )
863 /* Wrong type; never mind!.. but see below!
869 typedef const Lang::Coords2D ArgType;
870 RefCountPtr< ArgType > t = Helpers::try_cast_CoreArgument< ArgType >( piece );
871 pile_->push_back( RefCountPtr< const Lang::TextOperation >( new Lang::TextNewline( t->x_.get( ), t->y_.get( ) ) ) );
872 Kernel::ContRef cont = evalState->cont_;
873 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
874 evalState );
875 return;
877 catch( const NonLocalExit::NotThisType & ball )
879 /* Wrong type; never mind!.. but see below!
885 typedef const Lang::FloatPair ArgType;
886 RefCountPtr< ArgType > t = Helpers::try_cast_CoreArgument< ArgType >( piece );
887 Concrete::Length sz = evalState->dyn_->getTextState( )->size_;
888 pile_->push_back( RefCountPtr< const Lang::TextOperation >( new Lang::TextNewline( sz * t->x_, sz * t->y_ ) ) );
889 Kernel::ContRef cont = evalState->cont_;
890 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
891 evalState );
892 return;
894 catch( const NonLocalExit::NotThisType & ball )
896 /* Wrong type; never mind!.. but see below!
900 throw Exceptions::TypeMismatch( callLoc, piece->getTypeName( ), Helpers::typeSetString( Lang::TextOperation::staticTypeName( ), Lang::String::staticTypeName( ) ) );
903 void
904 Kernel::WarmText::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
906 if( pile_->empty( ) )
908 Kernel::ContRef cont = evalState->cont_;
909 cont->takeValue( Lang::THE_NULL2D,
910 evalState );
911 return;
914 Concrete::Length xmin = Concrete::HUGE_LENGTH;
915 Concrete::Length xmax = -Concrete::HUGE_LENGTH;
916 Concrete::Length ymin = Concrete::HUGE_LENGTH;
917 Concrete::Length ymax = -Concrete::HUGE_LENGTH;
920 Lang::Transform2D textMatrix( 1, 0, 0, 1, 0, 0 );
921 Lang::Transform2D textLineMatrix( 1, 0, 0, 1, 0, 0 );
922 typedef typeof *pile_ ListType;
923 for( ListType::const_iterator i = pile_->begin( ); i != pile_->end( ); ++i )
925 (*i)->measure( & textMatrix, & textLineMatrix, & xmin, & ymin, & xmax, & ymax );
929 Lang::ElementaryPath2D * bbox = new Lang::ElementaryPath2D;
931 if( xmin < Concrete::HUGE_LENGTH )
933 bbox->push_back( new Concrete::PathPoint2D( xmin, ymin ) );
934 bbox->push_back( new Concrete::PathPoint2D( xmin, ymax ) );
935 bbox->push_back( new Concrete::PathPoint2D( xmax, ymax ) );
936 bbox->push_back( new Concrete::PathPoint2D( xmax, ymin ) );
937 bbox->close( );
940 Kernel::ContRef cont = evalState->cont_;
941 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::Text( evalState->dyn_->getTextState( ),
942 pile_,
943 RefCountPtr< const Lang::ElementaryPath2D >( bbox ) ) ),
944 evalState );
947 void
948 Kernel::WarmText::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
950 throw Exceptions::MiscellaneousRequirement( strrefdup( "A text graphics state cannot be peeked." ) );
953 void
954 Kernel::WarmText::gcMark( Kernel::GCMarkedSet & marked )
956 typedef typeof *pile_ ListType;
957 for( ListType::const_iterator i = pile_->begin( ); i != pile_->end( ); ++i )
959 const_cast< Lang::TextOperation * >( i->getPtr( ) )->gcMark( marked );
964 Kernel::WarmType3Font::WarmType3Font( )
965 : metrics_( new FontMetrics::AFM( ) ), size_( -1 )
967 metrics_->capHeight_ = std::numeric_limits< double >::signaling_NaN( );
968 metrics_->xHeight_ = std::numeric_limits< double >::signaling_NaN( );
969 metrics_->ascender_ = std::numeric_limits< double >::signaling_NaN( );
970 metrics_->descender_ = std::numeric_limits< double >::signaling_NaN( );
971 metrics_->leading_ = std::numeric_limits< double >::signaling_NaN( );
972 metrics_->stdHW_ = std::numeric_limits< double >::signaling_NaN( );
973 metrics_->stdVW_ = std::numeric_limits< double >::signaling_NaN( );
974 metrics_->fontBBoxXMin_ = 0;
975 metrics_->fontBBoxXMax_ = -1;
977 horizontalMetrics_typed_ = new FontMetrics::SingleByte_WritingDirectionMetrics( );
978 metrics_->horizontalMetrics_ = RefCountPtr< FontMetrics::WritingDirectionMetrics >( horizontalMetrics_typed_ );
979 horizontalMetrics_typed_->underlinePosition_ = std::numeric_limits< double >::signaling_NaN( );
980 horizontalMetrics_typed_->underlineThickness_ = std::numeric_limits< double >::signaling_NaN( );
981 horizontalMetrics_typed_->italicAngleRadians_ = std::numeric_limits< double >::signaling_NaN( );
984 Kernel::WarmType3Font::~WarmType3Font( )
987 RefCountPtr< const Lang::Class > Kernel::WarmType3Font::TypeID( new Lang::SystemFinalClass( strrefdup( "#Type3Font" ) ) );
988 TYPEINFOIMPL_STATE( WarmType3Font );
990 void
991 Kernel::WarmType3Font::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
995 typedef const Lang::Type3Glyph ArgType;
996 glyphs_.push_back( Helpers::try_cast_CoreArgument< ArgType >( piece ) );
997 Kernel::ContRef cont = evalState->cont_;
998 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
999 evalState );
1000 return;
1002 catch( const NonLocalExit::NotThisType & ball )
1004 /* Wrong type; never mind!.. but see below!
1010 typedef const Lang::KernedText ArgType;
1011 kernings_.push_back( Helpers::try_cast_CoreArgument< ArgType >( piece ) );
1012 Kernel::ContRef cont = evalState->cont_;
1013 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
1014 evalState );
1015 return;
1017 catch( const NonLocalExit::NotThisType & ball )
1019 /* Wrong type; never mind!.. but see below!
1025 typedef const Lang::TaggedValue2D ArgType;
1026 RefCountPtr< ArgType > taggedVal = Helpers::try_cast_CoreArgument< ArgType >( piece );
1028 RefCountPtr< const char > tagMem = Lang::Symbol::nameFromKey( taggedVal->key( ) );
1029 const char * tag = tagMem.getPtr( );
1030 RefCountPtr< const Lang::Value > val = taggedVal->val( );
1032 if( strcmp( tag, "size" ) == 0 )
1034 if( size_ > 0 )
1036 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1038 typedef const Lang::Length ValType;
1039 size_ = Helpers::down_cast< ValType >( val, callLoc )->get( );
1040 if( ! ( size_ > 0 ) )
1042 throw Exceptions::OutOfRange( callLoc, "The size must be positive." );
1045 else if( strcmp( tag, "FontName" ) == 0 )
1047 if( metrics_->fontName_ != NullPtr< const char >( ) )
1049 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1051 typedef const Lang::Symbol ValType;
1052 metrics_->fontName_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1054 else if( strcmp( tag, "FullName" ) == 0 )
1056 if( metrics_->fullName_ != NullPtr< const char >( ) )
1058 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1060 typedef const Lang::String ValType;
1061 metrics_->fullName_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1063 else if( strcmp( tag, "FamilyName" ) == 0 )
1065 if( metrics_->familyName_ != NullPtr< const char >( ) )
1067 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1069 typedef const Lang::Symbol ValType;
1070 metrics_->familyName_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1072 else if( strcmp( tag, "Weight" ) == 0 )
1076 typedef const Lang::Symbol ValType;
1077 RefCountPtr< const char > typedVal = Helpers::try_cast_CoreArgument< ValType >( val )->name( );
1078 if( metrics_->weight_ != NullPtr< const char >( ) )
1080 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1082 static std::set< const char *, charPtrLess > legalStretchValues;
1083 if( legalStretchValues.empty( ) )
1085 initializeLegalStrechValues( & legalStretchValues );
1087 if( legalStretchValues.find( typedVal.getPtr( ) ) == legalStretchValues.end( ) )
1089 throw Exceptions::OutOfRange( callLoc, "The 'Weight value is illegal. Please refer to the PDF specification." );
1091 metrics_->weight_ = typedVal;
1092 goto OK;
1094 catch( const NonLocalExit::NotThisType & ball )
1096 /* Wrong type; never mind!.. but see below!
1102 typedef const Lang::Integer ValType;
1103 RefCountPtr< ValType > casted_val = Helpers::try_cast_CoreArgument< ValType >( val );
1104 if( metrics_->weightNumber_ > 0 )
1106 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1108 if( casted_val->val_ % 100 != 0 )
1110 throw Exceptions::OutOfRange( callLoc, "The 'Weight number must be divisible by 100." );
1112 if( casted_val->val_ < 100 || casted_val->val_ > 900 )
1114 throw Exceptions::OutOfRange( callLoc, "The 'Weight number must be in the range [ 100, 900 ]." );
1116 metrics_->weightNumber_ = casted_val->val_;
1117 goto OK;
1119 catch( const NonLocalExit::NotThisType & ball )
1121 /* Wrong type; never mind!.. but see below!
1125 throw Exceptions::TypeMismatch( callLoc, val->getTypeName( ), Helpers::typeSetString( Lang::String::staticTypeName( ), Lang::Integer::staticTypeName( ) ) );
1127 else if( strcmp( tag, "Version" ) == 0 )
1129 if( metrics_->version_ != NullPtr< const char >( ) )
1131 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1133 typedef const Lang::String ValType;
1134 metrics_->version_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1136 else if( strcmp( tag, "Notice" ) == 0 )
1138 if( metrics_->notice_ != NullPtr< const char >( ) )
1140 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1142 typedef const Lang::String ValType;
1143 metrics_->notice_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1145 else if( strcmp( tag, "EncodingScheme" ) == 0 )
1147 if( metrics_->encodingScheme_ != NullPtr< const char >( ) )
1149 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1151 typedef const Lang::Symbol ValType;
1152 metrics_->encodingScheme_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1154 else if( strcmp( tag, "CharacterSet" ) == 0 )
1156 if( metrics_->characterSet_ != NullPtr< const char >( ) )
1158 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1160 typedef const Lang::Symbol ValType;
1161 metrics_->characterSet_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1163 else if( strcmp( tag, "Comment" ) == 0 )
1165 typedef const Lang::String ValType;
1166 RefCountPtr< ValType > typedVal = Helpers::down_cast< ValType >( val, callLoc );
1167 metrics_->comments_.push_back( FontMetrics::AFM::AssortedInfo( tagMem, typedVal->val_ ) );
1169 else if( strcmp( tag, "CapHeight" ) == 0 )
1171 if( ! IS_NAN( metrics_->capHeight_ ) )
1173 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1175 if( ! ( size_ > 0 ) )
1177 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1179 typedef const Lang::Length ValType;
1180 metrics_->capHeight_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1182 else if( strcmp( tag, "XHeight" ) == 0 )
1184 if( ! IS_NAN( metrics_->xHeight_ ) )
1186 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1188 if( ! ( size_ > 0 ) )
1190 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1192 typedef const Lang::Length ValType;
1193 metrics_->xHeight_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1195 else if( strcmp( tag, "Ascent" ) == 0 )
1197 if( ! IS_NAN( metrics_->ascender_ ) )
1199 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1201 if( ! ( size_ > 0 ) )
1203 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1205 typedef const Lang::Length ValType;
1206 metrics_->ascender_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1208 else if( strcmp( tag, "Descent" ) == 0 )
1210 if( ! IS_NAN( metrics_->descender_ ) )
1212 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1214 if( ! ( size_ > 0 ) )
1216 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1218 typedef const Lang::Length ValType;
1219 metrics_->descender_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1221 else if( strcmp( tag, "Leading" ) == 0 )
1223 if( ! IS_NAN( metrics_->leading_ ) )
1225 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1227 if( ! ( size_ > 0 ) )
1229 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1231 typedef const Lang::Length ValType;
1232 metrics_->leading_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1234 else if( strcmp( tag, "StemH" ) == 0 )
1236 if( ! IS_NAN( metrics_->stdHW_ ) )
1238 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1240 if( ! ( size_ > 0 ) )
1242 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1244 typedef const Lang::Length ValType;
1245 metrics_->stdHW_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1247 else if( strcmp( tag, "StemV" ) == 0 )
1249 if( ! IS_NAN( metrics_->stdVW_ ) )
1251 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1253 if( ! ( size_ > 0 ) )
1255 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1257 typedef const Lang::Length ValType;
1258 metrics_->stdVW_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1260 else if( strcmp( tag, "FontBBox" ) == 0 )
1262 if( metrics_->fontBBoxXMax_ >= metrics_->fontBBoxXMin_ )
1264 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1266 if( ! ( size_ > 0 ) )
1268 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1270 typedef const Lang::ElementaryPath2D ValType;
1271 RefCountPtr< ValType > casted_val = Helpers::elementaryPathTry2D( val );
1272 Concrete::Coords2D llcorner( 0, 0 );
1273 Concrete::Coords2D urcorner( 0, 0 );
1274 if( ! casted_val->boundingRectangle( & llcorner, & urcorner ) )
1276 throw Exceptions::OutOfRange( callLoc, "The path was empty." );
1278 metrics_->fontBBoxXMin_ = llcorner.x_ / size_;
1279 metrics_->fontBBoxYMin_ = llcorner.y_ / size_;
1280 metrics_->fontBBoxXMax_ = urcorner.x_ / size_;
1281 metrics_->fontBBoxYMax_ = urcorner.y_ / size_;
1283 else if( strcmp( tag, "UnderlinePosition" ) == 0 )
1285 if( ! IS_NAN( horizontalMetrics_typed_->underlinePosition_ ) )
1287 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1289 if( ! ( size_ > 0 ) )
1291 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1293 typedef const Lang::Length ValType;
1294 horizontalMetrics_typed_->underlinePosition_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1296 else if( strcmp( tag, "UnderlineThickness" ) == 0 )
1298 if( ! IS_NAN( horizontalMetrics_typed_->underlineThickness_ ) )
1300 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1302 if( ! ( size_ > 0 ) )
1304 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1306 typedef const Lang::Length ValType;
1307 horizontalMetrics_typed_->underlineThickness_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1309 else if( strcmp( tag, "ItalicAngle" ) == 0 )
1311 if( ! IS_NAN( horizontalMetrics_typed_->italicAngleRadians_ ) )
1313 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1315 typedef const Lang::Float ValType;
1316 horizontalMetrics_typed_->italicAngleRadians_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1318 else
1320 typedef const Lang::String ValType;
1321 RefCountPtr< ValType > typedVal = Helpers::down_cast< ValType >( val, callLoc );
1322 metrics_->assortedGlobalInfo_.push_back( FontMetrics::AFM::AssortedInfo( tagMem, typedVal->val_ ) );
1326 Kernel::ContRef cont = evalState->cont_;
1327 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
1328 evalState );
1329 return;
1331 catch( const NonLocalExit::NotThisType & ball )
1333 /* Wrong type; never mind!.. but see below!
1337 throw Exceptions::TypeMismatch( callLoc, piece->getTypeName( ), Helpers::typeSetString( Lang::Type3Glyph::staticTypeName( ), Lang::KernedText::staticTypeName( ), Lang::TaggedValue2D::staticTypeName( ) ) );
1340 void
1341 Kernel::WarmType3Font::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1343 if( glyphs_.empty( ) )
1345 throw Exceptions::OutOfRange( callLoc, "A font without glyphs?!" );
1347 if( ! ( size_ > 0 ) )
1349 throw Exceptions::OutOfRange( callLoc, "Missing 'size." );
1351 if( strlen( metrics_->fontName_.getPtr( ) ) == 0 )
1353 throw Exceptions::OutOfRange( callLoc, "Missing 'FontName." );
1355 if( metrics_->weightNumber_ == 0 )
1357 metrics_->weightNumber_ = 400;
1359 bool findBBox = false;
1360 if( metrics_->fontBBoxXMax_ < metrics_->fontBBoxXMin_ )
1362 findBBox = true;
1365 Concrete::ReciprocalLength invSize = 1 / size_;
1367 metrics_->charCount_ = glyphs_.size( );
1368 metrics_->isCIDFont_ = false;
1370 size_t firstChar = INT_MAX;
1371 size_t lastChar = 0;
1373 // In the first scan of the glyphs, only firstChar and lastChar are computed. The other tasks are performed in the later scan.
1374 typedef typeof glyphs_ ListType;
1375 for( ListType::const_iterator i = glyphs_.begin( ); i != glyphs_.end( ); ++i )
1377 size_t code = (*i)->code( );
1378 if( code > 0 )
1380 firstChar = std::min( firstChar, code );
1381 lastChar = std::max( lastChar, code );
1386 RefCountPtr< SimplePDF::PDF_Vector > widths;
1388 RefCountPtr< SimplePDF::PDF_Object > stdWidth = SimplePDF::newFloat( 0 );
1389 widths->vec.resize( lastChar - firstChar + 1, stdWidth );
1391 RefCountPtr< SimplePDF::PDF_Dictionary > charProcs;
1392 RefCountPtr< SimplePDF::PDF_Resources > resources;
1393 // RefCountPtr< SimplePDF::PDF_Stream_out > toUnicode;
1395 horizontalMetrics_typed_->charData_.reserve( glyphs_.size( ) );
1398 // This is the main loop over all glyphs.
1399 typedef typeof glyphs_ ListType;
1400 for( ListType::const_iterator i = glyphs_.begin( ); i != glyphs_.end( ); ++i )
1402 size_t code = (*i)->code( );
1403 if( code > 0 )
1405 widths->vec[ code - firstChar ] = SimplePDF::newFloat( (*i)->widthX( ) );
1408 RefCountPtr< SimplePDF::PDF_Stream_out > glyphStream;
1409 (*i)->shipout( glyphStream->data, resources );
1410 charProcs->dic[ (*i)->name( ).getPtr( ) ] = SimplePDF::indirect( glyphStream, & Kernel::theIndirectObjectCount );
1412 size_t pos = horizontalMetrics_typed_->charData_.size( );
1413 FontMetrics::CharacterMetrics * glyphMetrics = new FontMetrics::CharacterMetrics( pos );
1414 (*i)->setupMetric( glyphMetrics, invSize );
1415 horizontalMetrics_typed_->charData_.push_back( glyphMetrics );
1416 horizontalMetrics_typed_->nameMap_[ (*i)->name( ) ] = pos;
1417 if( code > 0 )
1419 horizontalMetrics_typed_->codeMap_[ code ] = pos;
1422 if( findBBox )
1424 (*i)->enlargeBBox( & metrics_->fontBBoxXMin_, & metrics_->fontBBoxYMin_, & metrics_->fontBBoxXMax_, & metrics_->fontBBoxYMax_ );
1429 RefCountPtr< SimplePDF::PDF_Vector > fontBBox( new SimplePDF::PDF_Vector( metrics_->fontBBoxXMin_, metrics_->fontBBoxYMin_,
1430 metrics_->fontBBoxXMax_, metrics_->fontBBoxYMax_ ) );
1431 RefCountPtr< SimplePDF::PDF_Dictionary > fontDescriptor;
1432 (*fontDescriptor)[ "Type" ] = SimplePDF::newName( "FontDescriptor" );
1433 (*fontDescriptor)[ "FontName" ] = SimplePDF::newName( metrics_->fontName_.getPtr( ) );
1434 if( metrics_->familyName_.getPtr( ) != NullPtr< const char >( ) )
1436 (*fontDescriptor)[ "FontFamily" ] = SimplePDF::newName( metrics_->familyName_.getPtr( ) );
1438 if( metrics_->weight_.getPtr( ) != NullPtr< const char >( ) )
1440 // It has already been asserted that this value is legal.
1441 (*fontDescriptor)[ "FontStretch" ] = SimplePDF::newName( metrics_->weight_.getPtr( ) );
1443 if( metrics_->weightNumber_ > 0 )
1445 // It has already been asserted that this value is legal.
1446 (*fontDescriptor)[ "FontWeight" ] = SimplePDF::newInt( metrics_->weightNumber_ );
1448 (*fontDescriptor)[ "Flags" ] = SimplePDF::newInt( (size_t)(1) << ( 6 - 1 ) ); // This is just the "Nonsymbolic" flag.
1449 (*fontDescriptor)[ "FontBBox" ] = fontBBox;
1450 if( ! IS_NAN( horizontalMetrics_typed_->italicAngleRadians_ ) )
1452 (*fontDescriptor)[ "ItalicAngle" ] = SimplePDF::newFloat( ( 180 / M_PI ) * horizontalMetrics_typed_->italicAngleRadians_ );
1454 else
1456 throw Exceptions::OutOfRange( callLoc, "Missing 'ItalicAngle." );
1458 if( ! IS_NAN( metrics_->ascender_ ) )
1460 (*fontDescriptor)[ "Ascent" ] = SimplePDF::newFloat( metrics_->ascender_ );
1462 if( ! IS_NAN( metrics_->descender_ ) )
1464 (*fontDescriptor)[ "Descent" ] = SimplePDF::newFloat( metrics_->descender_ );
1466 if( ! IS_NAN( metrics_->leading_ ) )
1468 (*fontDescriptor)[ "Leading" ] = SimplePDF::newFloat( metrics_->leading_ );
1470 if( ! IS_NAN( metrics_->capHeight_ ) )
1472 (*fontDescriptor)[ "CapHeight" ] = SimplePDF::newFloat( metrics_->capHeight_ );
1474 if( ! IS_NAN( metrics_->xHeight_ ) )
1476 (*fontDescriptor)[ "XHeight" ] = SimplePDF::newFloat( metrics_->xHeight_ );
1478 if( ! IS_NAN( metrics_->stdHW_ ) )
1480 (*fontDescriptor)[ "StemH" ] = SimplePDF::newFloat( metrics_->stdHW_ );
1482 if( ! IS_NAN( metrics_->stdVW_ ) )
1484 (*fontDescriptor)[ "StemV" ] = SimplePDF::newFloat( metrics_->stdVW_ );
1487 Concrete::Length the1bp( 1 );
1489 RefCountPtr< SimplePDF::PDF_Dictionary > dic;
1490 RefCountPtr< SimplePDF::PDF_Object > indirection = SimplePDF::indirect( dic, & Kernel::theIndirectObjectCount );
1491 (*dic)[ "Type" ] = SimplePDF::newName( "Font" );
1492 (*dic)[ "Subtype" ] = SimplePDF::newName( "Type3" );
1493 (*dic)[ "Encoding" ] = SimplePDF::newName( "MacRomanEncoding" );
1494 (*dic)[ "FontBBox" ] = fontBBox;
1495 (*dic)[ "FontMatrix" ] = RefCountPtr< SimplePDF::PDF_Vector >( new SimplePDF::PDF_Vector( the1bp * invSize, 0, 0, the1bp * invSize, 0, 0 ) );
1496 (*dic)[ "CharProcs" ] = charProcs;
1497 (*dic)[ "FirstChar" ] = SimplePDF::newInt( firstChar );
1498 (*dic)[ "LastChar" ] = SimplePDF::newInt( lastChar );
1499 (*dic)[ "Widths" ] = widths;
1500 (*dic)[ "FontDescriptor" ] = fontDescriptor;
1501 (*dic)[ "Resources" ] = SimplePDF::indirect( resources, & Kernel::theIndirectObjectCount );
1503 // {
1504 // static bool shown = false;
1505 // if( ! shown )
1506 // {
1507 // WARN_OR_THROW( Shapes::Exceptions::InternalError( "The ToUnicode CMap is not set up by Shapes.", true ) );
1508 // shown = true;
1509 // }
1510 // }
1511 // (*dic)[ "ToUnicode" ] = toUnicode;
1513 Kernel::ContRef cont = evalState->cont_;
1514 cont->takeValue( Kernel::ValueRef( new Lang::Type3Font( metrics_->fontName_,
1515 indirection,
1516 metrics_ ) ),
1517 evalState );
1520 void
1521 Kernel::WarmType3Font::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1523 throw Exceptions::MiscellaneousRequirement( strrefdup( "A type 3 font state cannot be peeked." ) );
1526 void
1527 Kernel::WarmType3Font::gcMark( Kernel::GCMarkedSet & marked )
1530 typedef typeof kernings_ ListType;
1531 for( ListType::const_iterator i = kernings_.begin( ); i != kernings_.end( ); ++i )
1533 const_cast< Lang::KernedText * >( i->getPtr( ) )->gcMark( marked );
1537 typedef typeof glyphs_ ListType;
1538 for( ListType::const_iterator i = glyphs_.begin( ); i != glyphs_.end( ); ++i )
1540 const_cast< Lang::Type3Glyph * >( i->getPtr( ) )->gcMark( marked );
1546 void
1547 Kernel::WarmType3Font::initializeLegalStrechValues( std::set< const char *, charPtrLess > * legalStretchValues )
1549 legalStretchValues->insert( "UltraCondensed" );
1550 legalStretchValues->insert( "ExtraCondensed" );
1551 legalStretchValues->insert( "Condensed" );
1552 legalStretchValues->insert( "SemiCondensed" );
1553 legalStretchValues->insert( "Normal" );
1554 legalStretchValues->insert( "SemiExpanded" );
1555 legalStretchValues->insert( "Expanded" );
1556 legalStretchValues->insert( "ExtraExpanded" );
1557 legalStretchValues->insert( "UltraExpanded" );
1561 Kernel::WarmRandomDevice::WarmRandomDevice( const char * deviceName )
1562 : deviceName_( deviceName )
1565 Kernel::WarmRandomDevice::~WarmRandomDevice( )
1568 RefCountPtr< const Lang::Class > Kernel::WarmRandomDevice::TypeID( new Lang::SystemFinalClass( strrefdup( "#RandomDevice" ) ) );
1569 TYPEINFOIMPL_STATE( WarmRandomDevice );
1571 void
1572 Kernel::WarmRandomDevice::read( char * dst, size_t sz )
1574 if( ! idev_.is_open( ) )
1576 idev_.open( deviceName_ );
1577 if( ! idev_.is_open( ) || ! idev_.good( ) )
1579 throw Exceptions::ExternalError( strrefdup( deviceName_ + std::string( " could not be opened for input." ) ) );
1583 idev_.read( dst, sz );
1586 void
1587 Kernel::WarmRandomDevice::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
1589 if( ! odev_.is_open( ) )
1591 odev_.open( deviceName_ );
1592 if( ! odev_.is_open( ) || ! odev_.good( ) )
1594 throw Exceptions::ExternalError( strrefdup( deviceName_ + std::string( " could not be opened for output." ) ) );
1598 piece->show( odev_ );
1599 Kernel::ContRef cont = evalState->cont_;
1600 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
1601 evalState );
1604 void
1605 Kernel::WarmRandomDevice::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1607 throw Exceptions::MiscellaneousRequirement( strrefdup( "The random device cannot be frozen." ) );
1610 void
1611 Kernel::WarmRandomDevice::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1613 if( ! idev_.is_open( ) )
1615 idev_.open( deviceName_ );
1616 if( ! idev_.is_open( ) || ! idev_.good( ) )
1618 throw Exceptions::ExternalError( strrefdup( deviceName_ + std::string( " could not be opened for output." ) ) );
1622 unsigned char tmp;
1623 idev_.read( reinterpret_cast< char * >( & tmp ), 1 );
1624 Kernel::ContRef cont = evalState->cont_;
1625 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::Integer( tmp ) ),
1626 evalState );
1629 void
1630 Kernel::WarmRandomDevice::gcMark( Kernel::GCMarkedSet & marked )
1634 Kernel::WarmTime::WarmTime( )
1637 Kernel::WarmTime::~WarmTime( )
1640 RefCountPtr< const Lang::Class > Kernel::WarmTime::TypeID( new Lang::SystemFinalClass( strrefdup( "#Time" ) ) );
1641 TYPEINFOIMPL_STATE( WarmTime );
1643 void
1644 Kernel::WarmTime::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
1646 throw Exceptions::MiscellaneousRequirement( strrefdup( "The time does not accept values." ) );
1649 void
1650 Kernel::WarmTime::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1652 throw Exceptions::MiscellaneousRequirement( strrefdup( "The time cannot be frozen." ) );
1655 void
1656 Kernel::WarmTime::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1658 time_t t = time( 0 );
1659 Kernel::ContRef cont = evalState->cont_;
1660 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::ChronologicalTime( t ) ),
1661 evalState );
1664 void
1665 Kernel::WarmTime::gcMark( Kernel::GCMarkedSet & marked )
1669 Kernel::WarmRandomState::WarmRandomState( char * state )
1670 : state_( state )
1673 Kernel::WarmRandomState::~WarmRandomState( )
1675 delete state_; // Let's hope this is not in use!
1678 RefCountPtr< const Lang::Class > Kernel::WarmRandomState::TypeID( new Lang::SystemFinalClass( strrefdup( "#RandomState" ) ) );
1679 TYPEINFOIMPL_STATE( WarmRandomState );
1681 void
1682 Kernel::WarmRandomState::setState( )
1684 setstate( state_ );
1687 void
1688 Kernel::WarmRandomState::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
1690 throw Exceptions::MiscellaneousRequirement( strrefdup( "A random state does not accept values." ) );
1693 void
1694 Kernel::WarmRandomState::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1696 throw Exceptions::MiscellaneousRequirement( strrefdup( "A random state cannot be frozen." ) );
1699 void
1700 Kernel::WarmRandomState::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1702 setState( );
1703 long tmp = random( );
1704 Kernel::ContRef cont = evalState->cont_;
1705 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::Integer( tmp ) ),
1706 evalState );
1709 void
1710 Kernel::WarmRandomState::gcMark( Kernel::GCMarkedSet & marked )
1714 Kernel::WarmColorInterpolator::WarmColorInterpolator( )
1715 : hasKey_( false ), colorType_( Lang::ColorInterpolator::UNDEFINED )
1718 Kernel::WarmColorInterpolator::~WarmColorInterpolator( )
1721 RefCountPtr< const Lang::Class > Kernel::WarmColorInterpolator::TypeID( new Lang::SystemFinalClass( strrefdup( "#ColorInterpolator" ) ) );
1722 TYPEINFOIMPL_STATE( WarmColorInterpolator );
1724 void
1725 Kernel::WarmColorInterpolator::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
1727 if( hasKey_ )
1729 switch( colorType_ )
1731 case Lang::ColorInterpolator::UNDEFINED:
1734 RGBcolor_->push_back( Helpers::down_cast< const Lang::RGB >( piece, callLoc )->components( ) );
1735 colorType_ = Lang::ColorInterpolator::RGB;
1736 break;
1738 catch( const Exceptions::TypeMismatch & )
1743 graycolor_->push_back( Helpers::down_cast< const Lang::Gray >( piece, callLoc )->components( ) );
1744 colorType_ = Lang::ColorInterpolator::GRAY;
1745 break;
1747 catch( const Exceptions::TypeMismatch & )
1752 CMYKcolor_->push_back( Helpers::down_cast< const Lang::CMYK >( piece, callLoc )->components( ) );
1753 colorType_ = Lang::ColorInterpolator::CMYK;
1754 break;
1756 catch( const Exceptions::TypeMismatch & )
1758 throw Exceptions::MiscellaneousRequirement( strrefdup( "Only colors can be passed to an interpolator." ) );
1760 case Lang::ColorInterpolator::RGB:
1761 RGBcolor_->push_back( Helpers::down_cast< const Lang::RGB >( piece, callLoc )->components( ) );
1762 break;
1764 case Lang::ColorInterpolator::GRAY:
1765 graycolor_->push_back( Helpers::down_cast< const Lang::Gray >( piece, callLoc )->components( ) );
1766 break;
1768 case Lang::ColorInterpolator::CMYK:
1769 CMYKcolor_->push_back( Helpers::down_cast< const Lang::CMYK >( piece, callLoc )->components( ) );
1770 break;
1773 else
1775 typedef const Lang::Float ArgType;
1776 double key = Helpers::down_cast< ArgType >( piece, callLoc )->val_;
1777 if( !key_->empty( ) && key < key_->back( ) )
1779 throw Exceptions::MiscellaneousRequirement( strrefdup( "Keys must be added in nondecreasing order to an interpolator." ) );
1781 else
1783 key_->push_back( key );
1787 hasKey_ = ! hasKey_;
1789 Kernel::ContRef cont = evalState->cont_;
1790 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
1791 evalState );
1794 void
1795 Kernel::WarmColorInterpolator::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1797 if( key_->empty( ) )
1799 throw Exceptions::MiscellaneousRequirement( strrefdup( "There are no colors that define the interpolation." ) );
1801 if( hasKey_ )
1803 throw Exceptions::MiscellaneousRequirement( strrefdup( "Missing color for the last key." ) );
1806 Kernel::ContRef cont = evalState->cont_;
1807 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::ColorInterpolator( key_, RGBcolor_, graycolor_, CMYKcolor_, colorType_ ) ),
1808 evalState );
1811 void
1812 Kernel::WarmColorInterpolator::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1814 throw Exceptions::MiscellaneousRequirement( strrefdup( "An interpolator cannot be peeked." ) );
1817 void
1818 Kernel::WarmColorInterpolator::gcMark( Kernel::GCMarkedSet & marked )
1822 namespace Shapes
1824 namespace Kernel
1827 class Mutator_vector_size : public Lang::CoreMutator
1829 public:
1830 Mutator_vector_size( const char * name )
1831 : CoreMutator( name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
1834 virtual void
1835 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1837 args.applyDefaults( callLoc );
1839 typedef Warm_vector StateType;
1840 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
1842 Kernel::ContRef cont = evalState->cont_;
1843 cont->takeValue( Kernel::ValueRef( new Lang::Integer( state->mem_->size( ) ) ),
1844 evalState );
1848 class Mutator_vector_resize : public Lang::CoreMutator
1850 public:
1851 Mutator_vector_resize( const char * name )
1852 : CoreMutator( name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
1854 formals_->appendEvaluatedCoreFormal( "size", Kernel::THE_SLOT_VARIABLE );
1855 formals_->appendEvaluatedCoreFormal( "fill", Kernel::THE_VOID_VARIABLE );
1857 virtual void
1858 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1860 args.applyDefaults( callLoc );
1862 typedef Warm_vector StateType;
1863 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
1865 typedef const Lang::Integer IndexType;
1866 IndexType::ValueType tmp = Helpers::down_cast_MutatorArgument< IndexType >( state, name_, args, 0, callLoc )->val_;
1867 if( tmp < 0 )
1869 throw Exceptions::CoreOutOfRange( new Interaction::MutatorLocation( state, name_ ), args, 0, "The size must be non-negative." );
1871 size_t newSize = static_cast< size_t >( tmp );
1873 if( newSize < state->mem_->size( ) )
1875 while( newSize < state->mem_->size( ) )
1877 state->mem_->pop_back( );
1880 else
1882 state->mem_->reserve( newSize );
1883 RefCountPtr< const Lang::Value > fill = args.getValue( 1 );
1884 while( newSize > state->mem_->size( ) )
1886 state->mem_->push_back( fill );
1890 Kernel::ContRef cont = evalState->cont_;
1891 cont->takeValue( Lang::THE_VOID,
1892 evalState );
1896 class Mutator_vector_reserve : public Lang::CoreMutator
1898 public:
1899 Mutator_vector_reserve( const char * name )
1900 : CoreMutator( name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
1902 formals_->appendEvaluatedCoreFormal( "size", Kernel::THE_SLOT_VARIABLE );
1904 virtual void
1905 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1907 args.applyDefaults( callLoc );
1909 typedef Warm_vector StateType;
1910 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
1912 typedef const Lang::Integer IndexType;
1913 IndexType::ValueType tmp = Helpers::down_cast_MutatorArgument< IndexType >( state, name_, args, 0, callLoc )->val_;
1914 if( tmp < 0 )
1916 throw Exceptions::CoreOutOfRange( new Interaction::MutatorLocation( state, name_ ), args, 0, "The size must be non-negative." );
1918 size_t newSize = static_cast< size_t >( tmp );
1920 state->mem_->reserve( newSize );
1922 Kernel::ContRef cont = evalState->cont_;
1923 cont->takeValue( Lang::THE_VOID,
1924 evalState );
1928 class Mutator_vector_set : public Lang::CoreMutator
1930 public:
1931 Mutator_vector_set( const char * name )
1932 : CoreMutator( name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
1934 formals_->appendEvaluatedCoreFormal( "index", Kernel::THE_SLOT_VARIABLE );
1935 formals_->appendEvaluatedCoreFormal( "value", Kernel::THE_SLOT_VARIABLE );
1937 virtual void
1938 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1940 args.applyDefaults( callLoc );
1942 typedef Warm_vector StateType;
1943 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
1945 typedef const Lang::Integer IndexType;
1946 IndexType::ValueType tmp = Helpers::down_cast_MutatorArgument< IndexType >( state, name_, args, 0, callLoc )->val_;
1947 if( tmp < 0 )
1949 throw Exceptions::CoreOutOfRange( new Interaction::MutatorLocation( state, name_ ), args, 0, "The index must be non-negative." );
1951 size_t index = static_cast< size_t >( tmp );
1952 if( index >= state->mem_->size( ) )
1954 throw Exceptions::CoreOutOfRange( new Interaction::MutatorLocation( state, name_ ), args, 0, "The index is out of range." );
1957 (*state->mem_)[ index ] = args.getValue( 1 );
1959 Kernel::ContRef cont = evalState->cont_;
1960 cont->takeValue( Lang::THE_VOID,
1961 evalState );
1965 class Mutator_vector_get : public Lang::CoreMutator
1967 public:
1968 Mutator_vector_get( const char * name )
1969 : CoreMutator( name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
1971 formals_->appendEvaluatedCoreFormal( "index", Kernel::THE_SLOT_VARIABLE );
1973 virtual void
1974 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1976 args.applyDefaults( callLoc );
1978 typedef Warm_vector StateType;
1979 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
1981 typedef const Lang::Integer IndexType;
1982 IndexType::ValueType tmp = Helpers::down_cast_MutatorArgument< IndexType >( state, name_, args, 0, callLoc )->val_;
1983 if( tmp < 0 )
1985 throw Exceptions::CoreOutOfRange( new Interaction::MutatorLocation( state, name_ ), args, 0, "The index must be non-negative." );
1987 size_t index = static_cast< size_t >( tmp );
1988 if( index >= state->mem_->size( ) )
1990 throw Exceptions::CoreOutOfRange( new Interaction::MutatorLocation( state, name_ ), args, 0, "The index is out of range." );
1993 Kernel::ContRef cont = evalState->cont_;
1994 cont->takeValue( (*state->mem_)[ index ],
1995 evalState );
2002 Kernel::Warm_vector::Warm_vector( )
2003 : mem_( new std::vector< Kernel::ValueRef > )
2006 Kernel::Warm_vector::~Warm_vector( )
2008 if( mem_ != 0 )
2010 delete mem_;
2014 void
2015 WarmVector_register_mutators( Lang::SystemFinalClass * dstClass )
2017 dstClass->registerMutator( new Kernel::Mutator_vector_size( "size" ) );
2018 dstClass->registerMutator( new Kernel::Mutator_vector_resize( "resize" ) );
2019 dstClass->registerMutator( new Kernel::Mutator_vector_reserve( "reserve" ) );
2020 dstClass->registerMutator( new Kernel::Mutator_vector_set( "set" ) );
2021 dstClass->registerMutator( new Kernel::Mutator_vector_get( "get" ) );
2024 RefCountPtr< const Lang::Class > Kernel::Warm_vector::TypeID( new Lang::SystemFinalClass( strrefdup( "#Array" ), WarmVector_register_mutators ) );
2025 TYPEINFOIMPL_STATE( Warm_vector );
2027 void
2028 Kernel::Warm_vector::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
2030 mem_->push_back( piece );
2031 Kernel::ContRef cont = evalState->cont_;
2032 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
2033 evalState );
2036 void
2037 Kernel::Warm_vector::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
2039 Kernel::ContRef cont = evalState->cont_;
2040 cont->takeValue( Kernel::ValueRef( new Lang::VectorFunction( mem_ ) ),
2041 evalState );
2042 mem_ = 0; /* The VectorFunction owns the memory now. */
2045 void
2046 Kernel::Warm_vector::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
2048 throw Exceptions::MiscellaneousRequirement( strrefdup( "An array state cannot be peeked. To inspect one entry at at time, use the <get> mutator." ) );
2051 void
2052 Kernel::Warm_vector::gcMark( Kernel::GCMarkedSet & marked )
2056 void
2057 Kernel::registerHot( Kernel::Environment * env )
2059 env->initDefine( Lang::CANVAS_ID, new Kernel::WarmGroup2D );
2060 env->initDefine( Lang::CATALOG_ID, new Kernel::WarmCatalog );
2061 env->initDefine( Lang::THE_NAMESPACE_Shapes_IO, "stdout", new Kernel::WarmOstream( std::cout ) );
2062 env->initDefine( Lang::THE_NAMESPACE_Shapes_IO, "stderr", new Kernel::WarmOstream( std::cerr ) );
2063 env->initDefine( Lang::THE_NAMESPACE_Shapes_Numeric_Random, "randomdevice", new Kernel::WarmRandomDevice( "/dev/urandom" ) );
2064 env->initDefine( Lang::THE_NAMESPACE_Shapes, "time", new Kernel::WarmTime );
2065 env->initDefine( Lang::THE_NAMESPACE_Shapes, "ignore", new Kernel::WarmIgnore );
2067 env->initDefine( Lang::THE_NAMESPACE_Shapes, "newIgnore", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmIgnore > ) );
2068 env->initDefine( Lang::THE_NAMESPACE_Shapes_Graphics, "newGroup", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmGroup2D > ) );
2069 env->initDefine( Lang::THE_NAMESPACE_Shapes_Graphics3D, "newGroup", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmGroup3D > ) );
2070 env->initDefine( Lang::THE_NAMESPACE_Shapes_Graphics3D, "newZBuf", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmZBuf > ) );
2071 env->initDefine( Lang::THE_NAMESPACE_Shapes_Graphics3D, "newZSorter", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmZSorter > ) );
2072 env->initDefine( Lang::THE_NAMESPACE_Shapes_Graphics3D, "newLights", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmGroupLights > ) );
2073 env->initDefine( Lang::THE_NAMESPACE_Shapes_String, "newString", Kernel::ValueRef( new Lang::HotDefault< Kernel::Warm_ostringstream > ) );
2074 env->initDefine( Lang::THE_NAMESPACE_Shapes, "newTimer", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmTimer > ) );
2075 env->initDefine( Lang::THE_NAMESPACE_Shapes_Text, "newText", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmText > ) );
2076 env->initDefine( Lang::THE_NAMESPACE_Shapes_Text, "newFont", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmType3Font > ) );
2077 env->initDefine( Lang::THE_NAMESPACE_Shapes_Traits, "newColorInterpolator", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmColorInterpolator > ) );
2078 env->initDefine( Lang::THE_NAMESPACE_Shapes_Data, "newArray", Kernel::ValueRef( new Lang::HotDefault< Kernel::Warm_vector > ) );