Example: Changed glyph-outline.shape for use with FontConfig.
[shapes.git] / source / hottypes.cc
blobfb8b55efbff48b148b17b2682e49ee84a8c3c27d
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 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"
32 #include <sstream>
33 #include <limits>
34 #include <sys/resource.h>
35 #include <cstdlib>
36 #include <cstring>
38 using namespace Shapes;
41 Lang::Hot::Hot::Hot( )
42 { }
44 Lang::Hot::~Hot( )
45 { }
47 RefCountPtr< const Lang::Class > Lang::Hot::TypeID( new Lang::SystemFinalClass( strrefdup( "Hot" ) ) );
48 TYPEINFOIMPL( Hot );
51 Lang::HotTriple::HotTriple( const RefCountPtr< const Lang::Value > & init, RefCountPtr< const Lang::Function > update, RefCountPtr< const Lang::Function > result )
52 : init_( init ), update_( update ), result_( result )
53 { }
55 Lang::HotTriple::~HotTriple( )
56 { }
58 Kernel::State *
59 Lang::HotTriple::newState( ) const
61 return new Kernel::WarmTriple( init_, update_, result_ );
64 void
65 Lang::HotTriple::gcMark( Kernel::GCMarkedSet & marked )
67 const_cast< Lang::Value * >( init_.getPtr( ) )->gcMark( marked );
68 const_cast< Lang::Function * >( update_.getPtr( ) )->gcMark( marked );
69 const_cast< Lang::Function * >( result_.getPtr( ) )->gcMark( marked );
74 Lang::HotRandomSeed::HotRandomSeed( size_t sz, Kernel::WarmRandomDevice * dev )
75 : sz_( sz ), state_( new char[ sz ] )
77 char * oldState = initstate( 1, state_, sz_ );
78 dev->read( state_, sz_ );
79 setstate( oldState );
82 Lang::HotRandomSeed::HotRandomSeed( size_t sz, unsigned long seed )
83 : sz_( sz ), state_( new char[ sz ] )
85 char * oldState = initstate( seed, state_, sz_ );
86 setstate( oldState );
89 Lang::HotRandomSeed::~HotRandomSeed( )
91 delete state_;
94 Kernel::State *
95 Lang::HotRandomSeed::newState( ) const
97 char * stateCopy = new char[ sz_ ];
98 memcpy( stateCopy, state_, sz_ );
99 return new Kernel::WarmRandomState( stateCopy ); // This handles ownership to the new state.
102 void
103 Lang::HotRandomSeed::gcMark( Kernel::GCMarkedSet & marked )
109 Kernel::WarmTriple::WarmTriple( const RefCountPtr< const Lang::Value > & pile, RefCountPtr< const Lang::Function > update, RefCountPtr< const Lang::Function > result )
110 : pile_( pile ), update_( update ), result_( result )
113 Kernel::WarmTriple::~WarmTriple( )
116 RefCountPtr< const Lang::Class > Kernel::WarmTriple::TypeID( new Lang::SystemFinalClass( strrefdup( "#UserState" ) ) );
117 TYPEINFOIMPL_STATE( WarmTriple );
119 void
120 Kernel::WarmTriple::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
122 /* This seems dangerous. I have not verified that pile will still exist when the continuation below is invoked.
124 evalState->cont_ = Kernel::ContRef( new Kernel::StmtStoreValueContinuation( & pile_,
125 evalState->cont_,
126 callLoc ) );
127 update_->call( evalState, pile_, piece, callLoc );
130 void
131 Kernel::WarmTriple::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
133 /* The right continuation is set by the calling variable.
135 result_->call( evalState, pile_, callLoc );
138 void
139 Kernel::WarmTriple::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
141 /* The right continuation is set by the calling variable.
143 result_->call( evalState, pile_, callLoc );
146 void
147 Kernel::WarmTriple::gcMark( Kernel::GCMarkedSet & marked )
149 const_cast< Lang::Value * >( pile_.getPtr( ) )->gcMark( marked );
150 const_cast< Lang::Function * >( update_.getPtr( ) )->gcMark( marked );
151 const_cast< Lang::Function * >( result_.getPtr( ) )->gcMark( marked );
155 Kernel::WarmIgnore::WarmIgnore( )
158 Kernel::WarmIgnore::~WarmIgnore( )
161 RefCountPtr< const Lang::Class > Kernel::WarmIgnore::TypeID( new Lang::SystemFinalClass( strrefdup( "#Ignore" ) ) );
162 TYPEINFOIMPL_STATE( WarmIgnore );
164 void
165 Kernel::WarmIgnore::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
167 // Ignore piece!
169 Kernel::ContRef cont = evalState->cont_;
170 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
171 evalState );
174 void
175 Kernel::WarmIgnore::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
177 throw Exceptions::MiscellaneousRequirement( strrefdup( "An ignore state cannot be frozen." ) );
180 void
181 Kernel::WarmIgnore::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
183 throw Exceptions::MiscellaneousRequirement( strrefdup( "An ignore state cannot be peeked." ) );
186 void
187 Kernel::WarmIgnore::gcMark( Kernel::GCMarkedSet & marked )
191 Kernel::WarmOstream::WarmOstream( std::ostream & os )
192 : os_( os )
195 Kernel::WarmOstream::~WarmOstream( )
198 RefCountPtr< const Lang::Class > Kernel::WarmOstream::TypeID( new Lang::SystemFinalClass( strrefdup( "#OutputStream" ) ) );
199 TYPEINFOIMPL_STATE( WarmOstream );
201 void
202 Kernel::WarmOstream::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
204 piece->show( os_ );
205 Kernel::ContRef cont = evalState->cont_;
206 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
207 evalState );
210 void
211 Kernel::WarmOstream::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
213 throw Exceptions::MiscellaneousRequirement( strrefdup( "A warm ostream cannot be frozen." ) );
216 void
217 Kernel::WarmOstream::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
219 throw Exceptions::MiscellaneousRequirement( strrefdup( "A warm ostream cannot be peeked." ) );
222 void
223 Kernel::WarmOstream::gcMark( Kernel::GCMarkedSet & marked )
227 Kernel::Warm_ostringstream::Warm_ostringstream( )
230 Kernel::Warm_ostringstream::~Warm_ostringstream( )
233 RefCountPtr< const Lang::Class > Kernel::Warm_ostringstream::TypeID( new Lang::SystemFinalClass( strrefdup( "#StringConcatenator" ) ) );
234 TYPEINFOIMPL_STATE( Warm_ostringstream );
236 void
237 Kernel::Warm_ostringstream::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
239 piece->show( os_ );
240 Kernel::ContRef cont = evalState->cont_;
241 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
242 evalState );
245 void
246 Kernel::Warm_ostringstream::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
248 Kernel::ContRef cont = evalState->cont_;
249 cont->takeValue( Kernel::ValueRef( new Lang::String( strrefdup( os_.str( ).c_str( ) ) ) ),
250 evalState );
253 void
254 Kernel::Warm_ostringstream::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
256 Kernel::ContRef cont = evalState->cont_;
257 cont->takeValue( Kernel::ValueRef( new Lang::String( strrefdup( os_.str( ).c_str( ) ) ) ),
258 evalState );
261 void
262 Kernel::Warm_ostringstream::gcMark( Kernel::GCMarkedSet & marked )
265 namespace Shapes
267 namespace Kernel
270 template< class T >
271 class Mutator_erase : public Lang::CoreFunction
273 public:
274 Mutator_erase( const char * title )
275 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
278 virtual void
279 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
281 args.applyDefaults( );
283 typedef T StateType;
284 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
285 state->erase( );
287 Kernel::ContRef cont = evalState->cont_;
288 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
289 evalState );
293 template< class T >
294 class Mutator_remove : public Lang::CoreFunction
296 public:
297 Mutator_remove( const char * title )
298 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
300 formals_->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE );
302 virtual void
303 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
305 args.applyDefaults( );
307 typedef const Lang::Symbol KeyType;
308 RefCountPtr< KeyType > key = Helpers::down_cast_CoreArgument< KeyType >( title_, args, 0, callLoc );
310 typedef T StateType;
311 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
312 state->remove( key->getKey( ) );
314 Kernel::ContRef cont = evalState->cont_;
315 cont->takeValue( Lang::THE_VOID,
316 evalState );
324 Kernel::WarmGroup2D::WarmGroup2D( )
325 : pile_( Lang::THE_NULL2D )
328 Kernel::WarmGroup2D::~WarmGroup2D( )
331 void
332 WarmGroup2D_register_mutators( Lang::SystemFinalClass * dstClass )
334 dstClass->registerMutator( new Kernel::Mutator_erase< Kernel::WarmGroup2D >( "erase" ) );
335 dstClass->registerMutator( new Kernel::Mutator_remove< Kernel::WarmGroup2D >( "remove" ) );
338 RefCountPtr< const Lang::Class > Kernel::WarmGroup2D::TypeID( new Lang::SystemFinalClass( strrefdup( "#Group2D" ), WarmGroup2D_register_mutators ) );
339 TYPEINFOIMPL_STATE( WarmGroup2D );
342 void
343 Kernel::WarmGroup2D::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
345 typedef const Lang::Drawable2D ArgType;
346 RefCountPtr< ArgType > arg = Helpers::down_cast< ArgType >( piece, callLoc );
349 /* For objects of user-defined type, we also check that the class inherits from Drawable.
351 typedef const Lang::Instance UserType;
352 UserType * obj = dynamic_cast< UserType * >( arg.getPtr( ) );
353 if( obj != 0 )
355 if( ! obj->getClass( )->method_isa( Lang::Drawable2D::TypeID ) )
357 throw Exceptions::TypeMismatch( callLoc, "2D insertion", piece->getTypeName( ), ArgType::staticTypeName( ) );
362 pile_ = RefCountPtr< const Lang::Group2D >( new Lang::GroupPair2D( arg,
363 pile_,
364 evalState->dyn_->getGraphicsState( ) ) );
365 Kernel::ContRef cont = evalState->cont_;
366 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
367 evalState );
370 void
371 Kernel::WarmGroup2D::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
373 Kernel::ContRef cont = evalState->cont_;
374 cont->takeValue( pile_,
375 evalState );
378 void
379 Kernel::WarmGroup2D::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
381 Kernel::ContRef cont = evalState->cont_;
382 cont->takeValue( pile_,
383 evalState );
386 void
387 Kernel::WarmGroup2D::erase( )
389 pile_ = Lang::THE_NULL2D;
392 void
393 Kernel::WarmGroup2D::remove( Lang::Symbol::KeyType key )
395 pile_ = pile_->removeShallow( key );
398 void
399 Kernel::WarmGroup2D::gcMark( Kernel::GCMarkedSet & marked )
401 const_cast< Lang::Group2D * >( pile_.getPtr( ) )->gcMark( marked );
406 Kernel::WarmGroup3D::WarmGroup3D( )
407 : pile_( Lang::THE_NULL3D )
410 Kernel::WarmGroup3D::~WarmGroup3D( )
413 void
414 WarmGroup3D_register_mutators( Lang::SystemFinalClass * dstClass )
416 dstClass->registerMutator( new Kernel::Mutator_erase< Kernel::WarmGroup3D >( "erase" ) );
417 dstClass->registerMutator( new Kernel::Mutator_remove< Kernel::WarmGroup3D >( "remove" ) );
420 RefCountPtr< const Lang::Class > Kernel::WarmGroup3D::TypeID( new Lang::SystemFinalClass( strrefdup( "#Group3D" ), WarmGroup3D_register_mutators ) );
421 TYPEINFOIMPL_STATE( WarmGroup3D );
423 void
424 Kernel::WarmGroup3D::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
426 pile_ = RefCountPtr< const Lang::Group3D >( new Lang::GroupPair3D( Helpers::down_cast< const Lang::Drawable3D >( piece, callLoc ),
427 pile_,
428 evalState->dyn_->getGraphicsState( ) ) );
429 Kernel::ContRef cont = evalState->cont_;
430 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
431 evalState );
434 void
435 Kernel::WarmGroup3D::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
437 Kernel::ContRef cont = evalState->cont_;
438 cont->takeValue( pile_,
439 evalState );
442 void
443 Kernel::WarmGroup3D::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
445 Kernel::ContRef cont = evalState->cont_;
446 cont->takeValue( pile_,
447 evalState );
450 void
451 Kernel::WarmGroup3D::erase( )
453 pile_ = Lang::THE_NULL3D;
456 void
457 Kernel::WarmGroup3D::remove( Lang::Symbol::KeyType key )
459 pile_ = pile_->removeShallow( key );
462 void
463 Kernel::WarmGroup3D::gcMark( Kernel::GCMarkedSet & marked )
465 const_cast< Lang::Group3D * >( pile_.getPtr( ) )->gcMark( marked );
469 Kernel::WarmGroupLights::WarmGroupLights( )
470 : pile_( Lang::THE_NULL_LIGHTS )
473 Kernel::WarmGroupLights::~WarmGroupLights( )
476 RefCountPtr< const Lang::Class > Kernel::WarmGroupLights::TypeID( new Lang::SystemFinalClass( strrefdup( "#GroupLights" ) ) );
477 TYPEINFOIMPL_STATE( WarmGroupLights );
479 void
480 Kernel::WarmGroupLights::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
482 pile_ = RefCountPtr< const Lang::LightGroup >( new Lang::LightPair( Helpers::down_cast< const Lang::LightSource >( piece, callLoc ),
483 pile_ ) );
484 Kernel::ContRef cont = evalState->cont_;
485 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
486 evalState );
489 void
490 Kernel::WarmGroupLights::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
492 Kernel::ContRef cont = evalState->cont_;
493 cont->takeValue( pile_,
494 evalState );
497 void
498 Kernel::WarmGroupLights::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
500 Kernel::ContRef cont = evalState->cont_;
501 cont->takeValue( pile_,
502 evalState );
505 void
506 Kernel::WarmGroupLights::gcMark( Kernel::GCMarkedSet & marked )
508 const_cast< Lang::LightGroup * >( pile_.getPtr( ) )->gcMark( marked );
512 Kernel::WarmZBuf::WarmZBuf( )
515 Kernel::WarmZBuf::~WarmZBuf( )
518 RefCountPtr< const Lang::Class > Kernel::WarmZBuf::TypeID( new Lang::SystemFinalClass( strrefdup( "#ZBuf" ) ) );
519 TYPEINFOIMPL_STATE( WarmZBuf );
521 void
522 Kernel::WarmZBuf::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
526 typedef const Lang::Drawable3D ArgType;
527 RefCountPtr< ArgType > drawable = Helpers::try_cast_CoreArgument< ArgType >( piece );
530 drawable->polygonize( pile_.getPtr( ), strokePile_.getPtr( ), evalState->dyn_, Lang::THE_3D_IDENTITY, drawable );
532 catch( const char * ball )
534 std::ostringstream oss;
535 oss << "Conversion to polygon failed with: " << ball ;
536 throw Exceptions::OutOfRange( callLoc, strrefdup( oss ) );
538 Kernel::ContRef cont = evalState->cont_;
539 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
540 evalState );
541 return;
543 catch( const NonLocalExit::NotThisType & ball )
545 /* Wrong type; never mind!.. but see below!
551 lightPile_->push_back( Helpers::try_cast_CoreArgument< const Lang::LightSource >( piece ) );
552 Kernel::ContRef cont = evalState->cont_;
553 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
554 evalState );
555 return;
557 catch( const NonLocalExit::NotThisType & ball )
559 /* Wrong type; never mind!.. but see below!
565 typedef const Lang::LightGroup ArgType;
566 RefCountPtr< ArgType > lights = Helpers::try_cast_CoreArgument< ArgType >( piece );
568 while( ! lights->isNull( ) )
570 typedef const Lang::LightPair PairType;
571 RefCountPtr< PairType > p = lights.down_cast< PairType >( );
572 lightPile_->push_back( p->car( ) );
573 lights = p->cdr( );
576 Kernel::ContRef cont = evalState->cont_;
577 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
578 evalState );
579 return;
581 catch( const NonLocalExit::NotThisType & ball )
583 /* Wrong type; never mind!.. but see below!
587 throw Exceptions::TypeMismatch( callLoc, piece->getTypeName( ), Helpers::typeSetString( Lang::Drawable3D::staticTypeName( ), Lang::LightSource::staticTypeName( ) ) );
590 void
591 Kernel::WarmZBuf::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
593 Kernel::ContRef cont = evalState->cont_;
594 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::ZBuf( pile_, strokePile_, lightPile_, evalState->dyn_->getGraphicsState( ) ) ),
595 evalState );
598 void
599 Kernel::WarmZBuf::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
601 throw Exceptions::MiscellaneousRequirement( strrefdup( "A z-buffer state cannot be peeked." ) );
604 void
605 Kernel::WarmZBuf::gcMark( Kernel::GCMarkedSet & marked )
608 typedef typeof *pile_ ListType;
609 for( ListType::const_iterator i = pile_->begin( ); i != pile_->end( ); ++i )
611 const_cast< Computation::PaintedPolygon3D * >( i->getPtr( ) )->gcMark( marked );
614 // {
615 // typedef typeof *strokePile_ ListType;
616 // for( ListType::const_iterator i = strokePile_->begin( ); i != strokePile_->end( ); ++i )
617 // {
618 // const_cast< Computation::StrokedLine3D * >( i->getPtr( ) )->gcMark( marked );
619 // }
620 // }
622 typedef typeof *lightPile_ ListType;
623 for( ListType::const_iterator i = lightPile_->begin( ); i != lightPile_->end( ); ++i )
625 const_cast< Lang::LightSource * >( i->getPtr( ) )->gcMark( marked );
631 Kernel::WarmZSorter::WarmZSorter( )
634 Kernel::WarmZSorter::~WarmZSorter( )
637 RefCountPtr< const Lang::Class > Kernel::WarmZSorter::TypeID( new Lang::SystemFinalClass( strrefdup( "#ZSorter" ) ) );
638 TYPEINFOIMPL_STATE( WarmZSorter );
640 void
641 Kernel::WarmZSorter::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
645 typedef const Lang::Drawable3D ArgType;
646 RefCountPtr< ArgType > drawable = Helpers::try_cast_CoreArgument< ArgType >( piece );
649 drawable->polygonize( pile_.getPtr( ), strokePile_.getPtr( ), evalState->dyn_, Lang::THE_3D_IDENTITY, drawable );
651 catch( const char * ball )
653 std::ostringstream oss;
654 oss << "Conversion to polygon failed with: " << ball ;
655 throw Exceptions::OutOfRange( callLoc, strrefdup( oss ) );
657 Kernel::ContRef cont = evalState->cont_;
658 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
659 evalState );
660 return;
662 catch( const NonLocalExit::NotThisType & ball )
664 /* Wrong type; never mind!.. but see below!
670 lightPile_->push_back( Helpers::try_cast_CoreArgument< const Lang::LightSource >( piece ) );
671 Kernel::ContRef cont = evalState->cont_;
672 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
673 evalState );
674 return;
676 catch( const NonLocalExit::NotThisType & ball )
678 /* Wrong type; never mind!.. but see below!
684 typedef const Lang::LightGroup ArgType;
685 RefCountPtr< ArgType > lights = Helpers::try_cast_CoreArgument< ArgType >( piece );
687 while( ! lights->isNull( ) )
689 typedef const Lang::LightPair PairType;
690 RefCountPtr< PairType > p = lights.down_cast< PairType >( );
691 lightPile_->push_back( p->car( ) );
692 lights = p->cdr( );
695 Kernel::ContRef cont = evalState->cont_;
696 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
697 evalState );
698 return;
700 catch( const NonLocalExit::NotThisType & ball )
702 /* Wrong type; never mind!.. but see below!
706 throw Exceptions::TypeMismatch( callLoc, piece->getTypeName( ), Helpers::typeSetString( Lang::Drawable3D::staticTypeName( ), Lang::LightSource::staticTypeName( ) ) );
709 void
710 Kernel::WarmZSorter::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
712 Kernel::ContRef cont = evalState->cont_;
713 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::ZSorter( pile_, strokePile_, lightPile_, evalState->dyn_->getGraphicsState( ) ) ),
714 evalState );
717 void
718 Kernel::WarmZSorter::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
720 throw Exceptions::MiscellaneousRequirement( strrefdup( "A z-sorter state cannot be peeked." ) );
723 void
724 Kernel::WarmZSorter::gcMark( Kernel::GCMarkedSet & marked )
727 typedef typeof *pile_ ListType;
728 for( ListType::const_iterator i = pile_->begin( ); i != pile_->end( ); ++i )
730 const_cast< Computation::PaintedPolygon3D * >( i->getPtr( ) )->gcMark( marked );
733 // {
734 // typedef typeof *strokePile_ ListType;
735 // for( ListType::const_iterator i = strokePile_->begin( ); i != strokePile_->end( ); ++i )
736 // {
737 // const_cast< Computation::StrokedLine3D * >( i->getPtr( ) )->gcMark( marked );
738 // }
739 // }
741 typedef typeof *lightPile_ ListType;
742 for( ListType::const_iterator i = lightPile_->begin( ); i != lightPile_->end( ); ++i )
744 const_cast< Lang::LightSource * >( i->getPtr( ) )->gcMark( marked );
750 Kernel::WarmTimer::WarmTimer( )
752 rusage ru;
753 int res = getrusage( RUSAGE_SELF, &ru );
754 if( res != 0 )
756 throw Exceptions::InternalError( strrefdup( "getrusage failed." ) );
758 start_ = ru.ru_utime;
761 Kernel::WarmTimer::~WarmTimer( )
764 RefCountPtr< const Lang::Class > Kernel::WarmTimer::TypeID( new Lang::SystemFinalClass( strrefdup( "#Timer" ) ) );
765 TYPEINFOIMPL_STATE( WarmTimer );
767 void
768 Kernel::WarmTimer::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
770 throw Exceptions::MiscellaneousRequirement( strrefdup( "A warm timer does not accept values. Please freeze to obtain the number of seconds since creation." ) );
773 void
774 Kernel::WarmTimer::freezeImpl( 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( "getrusage 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::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
794 rusage ru;
795 int res = getrusage( RUSAGE_SELF, &ru );
796 if( res != 0 )
798 throw Exceptions::InternalError( strrefdup( "grtrusage failed." ) );
800 timeval stop = ru.ru_utime;
801 double time1 = start_.tv_usec / 1000000.0 + start_.tv_sec;
802 double time2 = stop.tv_usec / 1000000.0 + stop.tv_sec;
804 Kernel::ContRef cont = evalState->cont_;
805 cont->takeValue( Kernel::ValueRef( new Lang::Float( time2 - time1 ) ),
806 evalState );
809 void
810 Kernel::WarmTimer::gcMark( Kernel::GCMarkedSet & marked )
814 Kernel::WarmText::WarmText( )
817 Kernel::WarmText::~WarmText( )
820 RefCountPtr< const Lang::Class > Kernel::WarmText::TypeID( new Lang::SystemFinalClass( strrefdup( "#Text" ) ) );
821 TYPEINFOIMPL_STATE( WarmText );
823 void
824 Kernel::WarmText::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
828 typedef const Lang::TextOperation ArgType;
829 pile_->push_back( Helpers::try_cast_CoreArgument< ArgType >( piece ) );
830 Kernel::ContRef cont = evalState->cont_;
831 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
832 evalState );
833 return;
835 catch( const NonLocalExit::NotThisType & ball )
837 /* Wrong type; never mind!.. but see below!
843 typedef const Lang::String ArgType;
844 RefCountPtr< ArgType > str = Helpers::try_cast_CoreArgument< ArgType >( piece );
845 Lang::KernedText * text = new Lang::KernedText( evalState->dyn_->getTextState( ), evalState->dyn_->getGraphicsState( ) );
846 text->pushString( str );
847 pile_->push_back( RefCountPtr< const Lang::TextOperation >( text ) );
848 Kernel::ContRef cont = evalState->cont_;
849 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
850 evalState );
851 return;
853 catch( const NonLocalExit::NotThisType & ball )
855 /* Wrong type; never mind!.. but see below!
861 typedef const Lang::Transform2D ArgType;
862 RefCountPtr< ArgType > tf = Helpers::try_cast_CoreArgument< ArgType >( piece );
863 pile_->push_back( RefCountPtr< const Lang::TextOperation >( new Lang::TextMoveto( tf ) ) );
864 Kernel::ContRef cont = evalState->cont_;
865 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
866 evalState );
867 return;
869 catch( const NonLocalExit::NotThisType & ball )
871 /* Wrong type; never mind!.. but see below!
877 typedef const Lang::Coords2D ArgType;
878 RefCountPtr< ArgType > t = Helpers::try_cast_CoreArgument< ArgType >( piece );
879 pile_->push_back( RefCountPtr< const Lang::TextOperation >( new Lang::TextNewline( t->x_.get( ), t->y_.get( ) ) ) );
880 Kernel::ContRef cont = evalState->cont_;
881 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
882 evalState );
883 return;
885 catch( const NonLocalExit::NotThisType & ball )
887 /* Wrong type; never mind!.. but see below!
893 typedef const Lang::FloatPair ArgType;
894 RefCountPtr< ArgType > t = Helpers::try_cast_CoreArgument< ArgType >( piece );
895 Concrete::Length sz = evalState->dyn_->getTextState( )->size_;
896 pile_->push_back( RefCountPtr< const Lang::TextOperation >( new Lang::TextNewline( sz * t->x_, sz * t->y_ ) ) );
897 Kernel::ContRef cont = evalState->cont_;
898 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
899 evalState );
900 return;
902 catch( const NonLocalExit::NotThisType & ball )
904 /* Wrong type; never mind!.. but see below!
908 throw Exceptions::TypeMismatch( callLoc, piece->getTypeName( ), Helpers::typeSetString( Lang::TextOperation::staticTypeName( ), Lang::String::staticTypeName( ) ) );
911 void
912 Kernel::WarmText::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
914 if( pile_->empty( ) )
916 Kernel::ContRef cont = evalState->cont_;
917 cont->takeValue( Lang::THE_NULL2D,
918 evalState );
919 return;
922 Concrete::Length xmin = Concrete::HUGE_LENGTH;
923 Concrete::Length xmax = -Concrete::HUGE_LENGTH;
924 Concrete::Length ymin = Concrete::HUGE_LENGTH;
925 Concrete::Length ymax = -Concrete::HUGE_LENGTH;
928 Lang::Transform2D textMatrix( 1, 0, 0, 1, 0, 0 );
929 Lang::Transform2D textLineMatrix( 1, 0, 0, 1, 0, 0 );
930 typedef typeof *pile_ ListType;
931 for( ListType::const_iterator i = pile_->begin( ); i != pile_->end( ); ++i )
933 (*i)->measure( & textMatrix, & textLineMatrix, & xmin, & ymin, & xmax, & ymax );
937 Lang::ElementaryPath2D * bbox = new Lang::ElementaryPath2D;
939 if( xmin < Concrete::HUGE_LENGTH )
941 bbox->push_back( new Concrete::PathPoint2D( xmin, ymin ) );
942 bbox->push_back( new Concrete::PathPoint2D( xmin, ymax ) );
943 bbox->push_back( new Concrete::PathPoint2D( xmax, ymax ) );
944 bbox->push_back( new Concrete::PathPoint2D( xmax, ymin ) );
945 bbox->close( );
948 Kernel::ContRef cont = evalState->cont_;
949 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::Text( evalState->dyn_->getGraphicsState( ),
950 evalState->dyn_->getTextState( ),
951 pile_,
952 RefCountPtr< const Lang::ElementaryPath2D >( bbox ) ) ),
953 evalState );
956 void
957 Kernel::WarmText::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
959 throw Exceptions::MiscellaneousRequirement( strrefdup( "A text graphics state cannot be peeked." ) );
962 void
963 Kernel::WarmText::gcMark( Kernel::GCMarkedSet & marked )
965 typedef typeof *pile_ ListType;
966 for( ListType::const_iterator i = pile_->begin( ); i != pile_->end( ); ++i )
968 const_cast< Lang::TextOperation * >( i->getPtr( ) )->gcMark( marked );
973 Kernel::WarmType3Font::WarmType3Font( )
974 : metrics_( new FontMetrics::AFM( ) ), size_( -1 )
976 metrics_->capHeight_ = std::numeric_limits< double >::signaling_NaN( );
977 metrics_->xHeight_ = std::numeric_limits< double >::signaling_NaN( );
978 metrics_->ascender_ = std::numeric_limits< double >::signaling_NaN( );
979 metrics_->descender_ = std::numeric_limits< double >::signaling_NaN( );
980 metrics_->leading_ = std::numeric_limits< double >::signaling_NaN( );
981 metrics_->stdHW_ = std::numeric_limits< double >::signaling_NaN( );
982 metrics_->stdVW_ = std::numeric_limits< double >::signaling_NaN( );
983 metrics_->fontBBoxXMin_ = 0;
984 metrics_->fontBBoxXMax_ = -1;
986 horizontalMetrics_typed_ = new FontMetrics::SingleByte_WritingDirectionMetrics( );
987 metrics_->horizontalMetrics_ = RefCountPtr< FontMetrics::WritingDirectionMetrics >( horizontalMetrics_typed_ );
988 horizontalMetrics_typed_->underlinePosition_ = std::numeric_limits< double >::signaling_NaN( );
989 horizontalMetrics_typed_->underlineThickness_ = std::numeric_limits< double >::signaling_NaN( );
990 horizontalMetrics_typed_->italicAngleRadians_ = std::numeric_limits< double >::signaling_NaN( );
993 Kernel::WarmType3Font::~WarmType3Font( )
996 RefCountPtr< const Lang::Class > Kernel::WarmType3Font::TypeID( new Lang::SystemFinalClass( strrefdup( "#Type3Font" ) ) );
997 TYPEINFOIMPL_STATE( WarmType3Font );
999 void
1000 Kernel::WarmType3Font::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
1004 typedef const Lang::Type3Glyph ArgType;
1005 glyphs_.push_back( Helpers::try_cast_CoreArgument< ArgType >( piece ) );
1006 Kernel::ContRef cont = evalState->cont_;
1007 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
1008 evalState );
1009 return;
1011 catch( const NonLocalExit::NotThisType & ball )
1013 /* Wrong type; never mind!.. but see below!
1019 typedef const Lang::KernedText ArgType;
1020 kernings_.push_back( Helpers::try_cast_CoreArgument< ArgType >( piece ) );
1021 Kernel::ContRef cont = evalState->cont_;
1022 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
1023 evalState );
1024 return;
1026 catch( const NonLocalExit::NotThisType & ball )
1028 /* Wrong type; never mind!.. but see below!
1034 typedef const Lang::TaggedValue2D ArgType;
1035 RefCountPtr< ArgType > taggedVal = Helpers::try_cast_CoreArgument< ArgType >( piece );
1037 RefCountPtr< const char > tagMem = Lang::Symbol::nameFromKey( taggedVal->key( ) );
1038 const char * tag = tagMem.getPtr( );
1039 RefCountPtr< const Lang::Value > val = taggedVal->val( );
1041 if( strcmp( tag, "size" ) == 0 )
1043 if( size_ > 0 )
1045 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1047 typedef const Lang::Length ValType;
1048 size_ = Helpers::down_cast< ValType >( val, callLoc )->get( );
1049 if( ! ( size_ > 0 ) )
1051 throw Exceptions::OutOfRange( callLoc, "The size must be positive." );
1054 else if( strcmp( tag, "FontName" ) == 0 )
1056 if( metrics_->fontName_ != NullPtr< const char >( ) )
1058 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1060 typedef const Lang::Symbol ValType;
1061 metrics_->fontName_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1063 else if( strcmp( tag, "FullName" ) == 0 )
1065 if( metrics_->fullName_ != NullPtr< const char >( ) )
1067 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1069 typedef const Lang::String ValType;
1070 metrics_->fullName_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1072 else if( strcmp( tag, "FamilyName" ) == 0 )
1074 if( metrics_->familyName_ != NullPtr< const char >( ) )
1076 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1078 typedef const Lang::Symbol ValType;
1079 metrics_->familyName_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1081 else if( strcmp( tag, "Weight" ) == 0 )
1085 typedef const Lang::Symbol ValType;
1086 RefCountPtr< const char > typedVal = Helpers::try_cast_CoreArgument< ValType >( val )->name( );
1087 if( metrics_->weight_ != NullPtr< const char >( ) )
1089 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1091 static std::set< const char *, charPtrLess > legalStretchValues;
1092 if( legalStretchValues.empty( ) )
1094 initializeLegalStrechValues( & legalStretchValues );
1096 if( legalStretchValues.find( typedVal.getPtr( ) ) == legalStretchValues.end( ) )
1098 throw Exceptions::OutOfRange( callLoc, "The 'Weight value is illegal. Please refer to the PDF specification." );
1100 metrics_->weight_ = typedVal;
1101 goto OK;
1103 catch( const NonLocalExit::NotThisType & ball )
1105 /* Wrong type; never mind!.. but see below!
1111 typedef const Lang::Integer ValType;
1112 RefCountPtr< ValType > casted_val = Helpers::try_cast_CoreArgument< ValType >( val );
1113 if( metrics_->weightNumber_ > 0 )
1115 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1117 if( casted_val->val_ % 100 != 0 )
1119 throw Exceptions::OutOfRange( callLoc, "The 'Weight number must be divisible by 100." );
1121 if( casted_val->val_ < 100 || casted_val->val_ > 900 )
1123 throw Exceptions::OutOfRange( callLoc, "The 'Weight number must be in the range [ 100, 900 ]." );
1125 metrics_->weightNumber_ = casted_val->val_;
1126 goto OK;
1128 catch( const NonLocalExit::NotThisType & ball )
1130 /* Wrong type; never mind!.. but see below!
1134 throw Exceptions::TypeMismatch( callLoc, val->getTypeName( ), Helpers::typeSetString( Lang::String::staticTypeName( ), Lang::Integer::staticTypeName( ) ) );
1136 else if( strcmp( tag, "Version" ) == 0 )
1138 if( metrics_->version_ != NullPtr< const char >( ) )
1140 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1142 typedef const Lang::String ValType;
1143 metrics_->version_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1145 else if( strcmp( tag, "Notice" ) == 0 )
1147 if( metrics_->notice_ != NullPtr< const char >( ) )
1149 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1151 typedef const Lang::String ValType;
1152 metrics_->notice_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1154 else if( strcmp( tag, "EncodingScheme" ) == 0 )
1156 if( metrics_->encodingScheme_ != NullPtr< const char >( ) )
1158 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1160 typedef const Lang::Symbol ValType;
1161 metrics_->encodingScheme_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1163 else if( strcmp( tag, "CharacterSet" ) == 0 )
1165 if( metrics_->characterSet_ != NullPtr< const char >( ) )
1167 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1169 typedef const Lang::Symbol ValType;
1170 metrics_->characterSet_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1172 else if( strcmp( tag, "Comment" ) == 0 )
1174 typedef const Lang::String ValType;
1175 RefCountPtr< ValType > typedVal = Helpers::down_cast< ValType >( val, callLoc );
1176 metrics_->comments_.push_back( FontMetrics::AFM::AssortedInfo( tagMem, typedVal->val_ ) );
1178 else if( strcmp( tag, "CapHeight" ) == 0 )
1180 if( ! IS_NAN( metrics_->capHeight_ ) )
1182 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1184 if( ! ( size_ > 0 ) )
1186 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1188 typedef const Lang::Length ValType;
1189 metrics_->capHeight_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1191 else if( strcmp( tag, "XHeight" ) == 0 )
1193 if( ! IS_NAN( metrics_->xHeight_ ) )
1195 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1197 if( ! ( size_ > 0 ) )
1199 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1201 typedef const Lang::Length ValType;
1202 metrics_->xHeight_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1204 else if( strcmp( tag, "Ascent" ) == 0 )
1206 if( ! IS_NAN( metrics_->ascender_ ) )
1208 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1210 if( ! ( size_ > 0 ) )
1212 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1214 typedef const Lang::Length ValType;
1215 metrics_->ascender_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1217 else if( strcmp( tag, "Descent" ) == 0 )
1219 if( ! IS_NAN( metrics_->descender_ ) )
1221 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1223 if( ! ( size_ > 0 ) )
1225 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1227 typedef const Lang::Length ValType;
1228 metrics_->descender_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1230 else if( strcmp( tag, "Leading" ) == 0 )
1232 if( ! IS_NAN( metrics_->leading_ ) )
1234 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1236 if( ! ( size_ > 0 ) )
1238 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1240 typedef const Lang::Length ValType;
1241 metrics_->leading_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1243 else if( strcmp( tag, "StemH" ) == 0 )
1245 if( ! IS_NAN( metrics_->stdHW_ ) )
1247 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1249 if( ! ( size_ > 0 ) )
1251 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1253 typedef const Lang::Length ValType;
1254 metrics_->stdHW_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1256 else if( strcmp( tag, "StemV" ) == 0 )
1258 if( ! IS_NAN( metrics_->stdVW_ ) )
1260 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1262 if( ! ( size_ > 0 ) )
1264 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1266 typedef const Lang::Length ValType;
1267 metrics_->stdVW_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1269 else if( strcmp( tag, "FontBBox" ) == 0 )
1271 if( metrics_->fontBBoxXMax_ >= metrics_->fontBBoxXMin_ )
1273 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1275 if( ! ( size_ > 0 ) )
1277 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1279 typedef const Lang::ElementaryPath2D ValType;
1280 RefCountPtr< ValType > casted_val = Helpers::elementaryPathTry2D( val );
1281 Concrete::Coords2D llcorner( 0, 0 );
1282 Concrete::Coords2D urcorner( 0, 0 );
1283 if( ! casted_val->boundingRectangle( & llcorner, & urcorner ) )
1285 throw Exceptions::OutOfRange( callLoc, "The path was empty." );
1287 metrics_->fontBBoxXMin_ = llcorner.x_ / size_;
1288 metrics_->fontBBoxYMin_ = llcorner.y_ / size_;
1289 metrics_->fontBBoxXMax_ = urcorner.x_ / size_;
1290 metrics_->fontBBoxYMax_ = urcorner.y_ / size_;
1292 else if( strcmp( tag, "UnderlinePosition" ) == 0 )
1294 if( ! IS_NAN( horizontalMetrics_typed_->underlinePosition_ ) )
1296 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1298 if( ! ( size_ > 0 ) )
1300 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1302 typedef const Lang::Length ValType;
1303 horizontalMetrics_typed_->underlinePosition_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1305 else if( strcmp( tag, "UnderlineThickness" ) == 0 )
1307 if( ! IS_NAN( horizontalMetrics_typed_->underlineThickness_ ) )
1309 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1311 if( ! ( size_ > 0 ) )
1313 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1315 typedef const Lang::Length ValType;
1316 horizontalMetrics_typed_->underlineThickness_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1318 else if( strcmp( tag, "ItalicAngle" ) == 0 )
1320 if( ! IS_NAN( horizontalMetrics_typed_->italicAngleRadians_ ) )
1322 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1324 typedef const Lang::Float ValType;
1325 horizontalMetrics_typed_->italicAngleRadians_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1327 else
1329 typedef const Lang::String ValType;
1330 RefCountPtr< ValType > typedVal = Helpers::down_cast< ValType >( val, callLoc );
1331 metrics_->assortedGlobalInfo_.push_back( FontMetrics::AFM::AssortedInfo( tagMem, typedVal->val_ ) );
1335 Kernel::ContRef cont = evalState->cont_;
1336 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
1337 evalState );
1338 return;
1340 catch( const NonLocalExit::NotThisType & ball )
1342 /* Wrong type; never mind!.. but see below!
1346 throw Exceptions::TypeMismatch( callLoc, piece->getTypeName( ), Helpers::typeSetString( Lang::Type3Glyph::staticTypeName( ), Lang::KernedText::staticTypeName( ), Lang::TaggedValue2D::staticTypeName( ) ) );
1349 void
1350 Kernel::WarmType3Font::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1352 if( glyphs_.empty( ) )
1354 throw Exceptions::OutOfRange( callLoc, "A font without glyphs?!" );
1356 if( ! ( size_ > 0 ) )
1358 throw Exceptions::OutOfRange( callLoc, "Missing 'size." );
1360 if( strlen( metrics_->fontName_.getPtr( ) ) == 0 )
1362 throw Exceptions::OutOfRange( callLoc, "Missing 'FontName." );
1364 if( metrics_->weightNumber_ == 0 )
1366 metrics_->weightNumber_ = 400;
1368 bool findBBox = false;
1369 if( metrics_->fontBBoxXMax_ < metrics_->fontBBoxXMin_ )
1371 findBBox = true;
1374 Concrete::ReciprocalLength invSize = 1 / size_;
1376 metrics_->charCount_ = glyphs_.size( );
1377 metrics_->isCIDFont_ = false;
1379 size_t firstChar = INT_MAX;
1380 size_t lastChar = 0;
1382 // In the first scan of the glyphs, only firstChar and lastChar are computed. The other tasks are performed in the later scan.
1383 typedef typeof glyphs_ ListType;
1384 for( ListType::const_iterator i = glyphs_.begin( ); i != glyphs_.end( ); ++i )
1386 size_t code = (*i)->code( );
1387 if( code > 0 )
1389 firstChar = std::min( firstChar, code );
1390 lastChar = std::max( lastChar, code );
1395 RefCountPtr< SimplePDF::PDF_Vector > widths;
1397 RefCountPtr< SimplePDF::PDF_Object > stdWidth = SimplePDF::newFloat( 0 );
1398 widths->vec.resize( lastChar - firstChar + 1, stdWidth );
1400 RefCountPtr< SimplePDF::PDF_Dictionary > charProcs;
1401 RefCountPtr< SimplePDF::PDF_Resources > resources;
1402 // RefCountPtr< SimplePDF::PDF_Stream_out > toUnicode;
1404 horizontalMetrics_typed_->charData_.reserve( glyphs_.size( ) );
1407 // This is the main loop over all glyphs.
1408 typedef typeof glyphs_ ListType;
1409 for( ListType::const_iterator i = glyphs_.begin( ); i != glyphs_.end( ); ++i )
1411 size_t code = (*i)->code( );
1412 if( code > 0 )
1414 widths->vec[ code - firstChar ] = SimplePDF::newFloat( (*i)->widthX( ) );
1417 RefCountPtr< SimplePDF::PDF_Stream_out > glyphStream;
1418 (*i)->shipout( glyphStream->data, resources );
1419 charProcs->dic[ (*i)->name( ).getPtr( ) ] = SimplePDF::indirect( glyphStream, & Kernel::theIndirectObjectCount );
1421 size_t pos = horizontalMetrics_typed_->charData_.size( );
1422 FontMetrics::CharacterMetrics * glyphMetrics = new FontMetrics::CharacterMetrics( pos );
1423 (*i)->setupMetric( glyphMetrics, invSize );
1424 horizontalMetrics_typed_->charData_.push_back( glyphMetrics );
1425 horizontalMetrics_typed_->nameMap_[ (*i)->name( ) ] = pos;
1426 if( code > 0 )
1428 horizontalMetrics_typed_->codeMap_[ code ] = pos;
1431 if( findBBox )
1433 (*i)->enlargeBBox( & metrics_->fontBBoxXMin_, & metrics_->fontBBoxYMin_, & metrics_->fontBBoxXMax_, & metrics_->fontBBoxYMax_ );
1438 RefCountPtr< SimplePDF::PDF_Vector > fontBBox( new SimplePDF::PDF_Vector( metrics_->fontBBoxXMin_, metrics_->fontBBoxYMin_,
1439 metrics_->fontBBoxXMax_, metrics_->fontBBoxYMax_ ) );
1440 RefCountPtr< SimplePDF::PDF_Dictionary > fontDescriptor;
1441 (*fontDescriptor)[ "Type" ] = SimplePDF::newName( "FontDescriptor" );
1442 (*fontDescriptor)[ "FontName" ] = SimplePDF::newName( metrics_->fontName_.getPtr( ) );
1443 if( metrics_->familyName_.getPtr( ) != NullPtr< const char >( ) )
1445 (*fontDescriptor)[ "FontFamily" ] = SimplePDF::newName( metrics_->familyName_.getPtr( ) );
1447 if( metrics_->weight_.getPtr( ) != NullPtr< const char >( ) )
1449 // It has already been asserted that this value is legal.
1450 (*fontDescriptor)[ "FontStretch" ] = SimplePDF::newName( metrics_->weight_.getPtr( ) );
1452 if( metrics_->weightNumber_ > 0 )
1454 // It has already been asserted that this value is legal.
1455 (*fontDescriptor)[ "FontWeight" ] = SimplePDF::newInt( metrics_->weightNumber_ );
1457 (*fontDescriptor)[ "Flags" ] = SimplePDF::newInt( (size_t)(1) << ( 6 - 1 ) ); // This is just the "Nonsymbolic" flag.
1458 (*fontDescriptor)[ "FontBBox" ] = fontBBox;
1459 if( ! IS_NAN( horizontalMetrics_typed_->italicAngleRadians_ ) )
1461 (*fontDescriptor)[ "ItalicAngle" ] = SimplePDF::newFloat( ( 180 / M_PI ) * horizontalMetrics_typed_->italicAngleRadians_ );
1463 else
1465 throw Exceptions::OutOfRange( callLoc, "Missing 'ItalicAngle." );
1467 if( ! IS_NAN( metrics_->ascender_ ) )
1469 (*fontDescriptor)[ "Ascent" ] = SimplePDF::newFloat( metrics_->ascender_ );
1471 if( ! IS_NAN( metrics_->descender_ ) )
1473 (*fontDescriptor)[ "Descent" ] = SimplePDF::newFloat( metrics_->descender_ );
1475 if( ! IS_NAN( metrics_->leading_ ) )
1477 (*fontDescriptor)[ "Leading" ] = SimplePDF::newFloat( metrics_->leading_ );
1479 if( ! IS_NAN( metrics_->capHeight_ ) )
1481 (*fontDescriptor)[ "CapHeight" ] = SimplePDF::newFloat( metrics_->capHeight_ );
1483 if( ! IS_NAN( metrics_->xHeight_ ) )
1485 (*fontDescriptor)[ "XHeight" ] = SimplePDF::newFloat( metrics_->xHeight_ );
1487 if( ! IS_NAN( metrics_->stdHW_ ) )
1489 (*fontDescriptor)[ "StemH" ] = SimplePDF::newFloat( metrics_->stdHW_ );
1491 if( ! IS_NAN( metrics_->stdVW_ ) )
1493 (*fontDescriptor)[ "StemV" ] = SimplePDF::newFloat( metrics_->stdVW_ );
1496 Concrete::Length the1bp( 1 );
1498 RefCountPtr< SimplePDF::PDF_Dictionary > dic;
1499 RefCountPtr< SimplePDF::PDF_Object > indirection = SimplePDF::indirect( dic, & Kernel::theIndirectObjectCount );
1500 (*dic)[ "Type" ] = SimplePDF::newName( "Font" );
1501 (*dic)[ "Subtype" ] = SimplePDF::newName( "Type3" );
1502 (*dic)[ "Encoding" ] = SimplePDF::newName( "MacRomanEncoding" );
1503 (*dic)[ "FontBBox" ] = fontBBox;
1504 (*dic)[ "FontMatrix" ] = RefCountPtr< SimplePDF::PDF_Vector >( new SimplePDF::PDF_Vector( the1bp * invSize, 0, 0, the1bp * invSize, 0, 0 ) );
1505 (*dic)[ "CharProcs" ] = charProcs;
1506 (*dic)[ "FirstChar" ] = SimplePDF::newInt( firstChar );
1507 (*dic)[ "LastChar" ] = SimplePDF::newInt( lastChar );
1508 (*dic)[ "Widths" ] = widths;
1509 (*dic)[ "FontDescriptor" ] = fontDescriptor;
1510 (*dic)[ "Resources" ] = SimplePDF::indirect( resources, & Kernel::theIndirectObjectCount );
1512 // {
1513 // static bool shown = false;
1514 // if( ! shown )
1515 // {
1516 // std::cerr << "Warning: The ToUnicode CMap is not setup by Shapes." << std::endl ;
1517 // shown = true;
1518 // }
1519 // }
1520 // (*dic)[ "ToUnicode" ] = toUnicode;
1522 Kernel::ContRef cont = evalState->cont_;
1523 cont->takeValue( Kernel::ValueRef( new Lang::Type3Font( metrics_->fontName_,
1524 indirection,
1525 metrics_ ) ),
1526 evalState );
1529 void
1530 Kernel::WarmType3Font::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1532 throw Exceptions::MiscellaneousRequirement( strrefdup( "A type 3 font state cannot be peeked." ) );
1535 void
1536 Kernel::WarmType3Font::gcMark( Kernel::GCMarkedSet & marked )
1539 typedef typeof kernings_ ListType;
1540 for( ListType::const_iterator i = kernings_.begin( ); i != kernings_.end( ); ++i )
1542 const_cast< Lang::KernedText * >( i->getPtr( ) )->gcMark( marked );
1546 typedef typeof glyphs_ ListType;
1547 for( ListType::const_iterator i = glyphs_.begin( ); i != glyphs_.end( ); ++i )
1549 const_cast< Lang::Type3Glyph * >( i->getPtr( ) )->gcMark( marked );
1555 void
1556 Kernel::WarmType3Font::initializeLegalStrechValues( std::set< const char *, charPtrLess > * legalStretchValues )
1558 legalStretchValues->insert( "UltraCondensed" );
1559 legalStretchValues->insert( "ExtraCondensed" );
1560 legalStretchValues->insert( "Condensed" );
1561 legalStretchValues->insert( "SemiCondensed" );
1562 legalStretchValues->insert( "Normal" );
1563 legalStretchValues->insert( "SemiExpanded" );
1564 legalStretchValues->insert( "Expanded" );
1565 legalStretchValues->insert( "ExtraExpanded" );
1566 legalStretchValues->insert( "UltraExpanded" );
1570 Kernel::WarmRandomDevice::WarmRandomDevice( const char * deviceName )
1571 : deviceName_( deviceName )
1574 Kernel::WarmRandomDevice::~WarmRandomDevice( )
1577 RefCountPtr< const Lang::Class > Kernel::WarmRandomDevice::TypeID( new Lang::SystemFinalClass( strrefdup( "#RandomDevice" ) ) );
1578 TYPEINFOIMPL_STATE( WarmRandomDevice );
1580 void
1581 Kernel::WarmRandomDevice::read( char * dst, size_t sz )
1583 if( ! idev_.is_open( ) )
1585 idev_.open( deviceName_ );
1586 if( ! idev_.is_open( ) || ! idev_.good( ) )
1588 throw Exceptions::ExternalError( strrefdup( deviceName_ + std::string( " could not be opened for input." ) ) );
1592 idev_.read( dst, sz );
1595 void
1596 Kernel::WarmRandomDevice::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
1598 if( ! odev_.is_open( ) )
1600 odev_.open( deviceName_ );
1601 if( ! odev_.is_open( ) || ! odev_.good( ) )
1603 throw Exceptions::ExternalError( strrefdup( deviceName_ + std::string( " could not be opened for output." ) ) );
1607 piece->show( odev_ );
1608 Kernel::ContRef cont = evalState->cont_;
1609 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
1610 evalState );
1613 void
1614 Kernel::WarmRandomDevice::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1616 throw Exceptions::MiscellaneousRequirement( strrefdup( "The random device cannot be frozen." ) );
1619 void
1620 Kernel::WarmRandomDevice::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1622 if( ! idev_.is_open( ) )
1624 idev_.open( deviceName_ );
1625 if( ! idev_.is_open( ) || ! idev_.good( ) )
1627 throw Exceptions::ExternalError( strrefdup( deviceName_ + std::string( " could not be opened for output." ) ) );
1631 unsigned char tmp;
1632 idev_.read( reinterpret_cast< char * >( & tmp ), 1 );
1633 Kernel::ContRef cont = evalState->cont_;
1634 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::Integer( tmp ) ),
1635 evalState );
1638 void
1639 Kernel::WarmRandomDevice::gcMark( Kernel::GCMarkedSet & marked )
1643 Kernel::WarmTime::WarmTime( )
1646 Kernel::WarmTime::~WarmTime( )
1649 RefCountPtr< const Lang::Class > Kernel::WarmTime::TypeID( new Lang::SystemFinalClass( strrefdup( "#Time" ) ) );
1650 TYPEINFOIMPL_STATE( WarmTime );
1652 void
1653 Kernel::WarmTime::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
1655 throw Exceptions::MiscellaneousRequirement( strrefdup( "The time does not accept values." ) );
1658 void
1659 Kernel::WarmTime::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1661 throw Exceptions::MiscellaneousRequirement( strrefdup( "The time cannot be frozen." ) );
1664 void
1665 Kernel::WarmTime::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1667 time_t t = time( 0 );
1668 Kernel::ContRef cont = evalState->cont_;
1669 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::ChronologicalTime( t ) ),
1670 evalState );
1673 void
1674 Kernel::WarmTime::gcMark( Kernel::GCMarkedSet & marked )
1678 Kernel::WarmRandomState::WarmRandomState( char * state )
1679 : state_( state )
1682 Kernel::WarmRandomState::~WarmRandomState( )
1684 delete state_; // Let's hope this is not in use!
1687 RefCountPtr< const Lang::Class > Kernel::WarmRandomState::TypeID( new Lang::SystemFinalClass( strrefdup( "#RandomState" ) ) );
1688 TYPEINFOIMPL_STATE( WarmRandomState );
1690 void
1691 Kernel::WarmRandomState::setState( )
1693 setstate( state_ );
1696 void
1697 Kernel::WarmRandomState::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
1699 throw Exceptions::MiscellaneousRequirement( strrefdup( "A random state does not accept values." ) );
1702 void
1703 Kernel::WarmRandomState::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1705 throw Exceptions::MiscellaneousRequirement( strrefdup( "A random state cannot be frozen." ) );
1708 void
1709 Kernel::WarmRandomState::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1711 setState( );
1712 long tmp = random( );
1713 Kernel::ContRef cont = evalState->cont_;
1714 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::Integer( tmp ) ),
1715 evalState );
1718 void
1719 Kernel::WarmRandomState::gcMark( Kernel::GCMarkedSet & marked )
1723 Kernel::WarmColorInterpolator::WarmColorInterpolator( )
1724 : hasKey_( false ), colorType_( Lang::ColorInterpolator::UNDEFINED )
1727 Kernel::WarmColorInterpolator::~WarmColorInterpolator( )
1730 RefCountPtr< const Lang::Class > Kernel::WarmColorInterpolator::TypeID( new Lang::SystemFinalClass( strrefdup( "#ColorInterpolator" ) ) );
1731 TYPEINFOIMPL_STATE( WarmColorInterpolator );
1733 void
1734 Kernel::WarmColorInterpolator::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
1736 if( hasKey_ )
1738 switch( colorType_ )
1740 case Lang::ColorInterpolator::UNDEFINED:
1743 RGBcolor_->push_back( Helpers::down_cast< const Lang::RGB >( piece, callLoc )->components( ) );
1744 colorType_ = Lang::ColorInterpolator::RGB;
1745 break;
1747 catch( const Exceptions::TypeMismatch & )
1752 graycolor_->push_back( Helpers::down_cast< const Lang::Gray >( piece, callLoc )->components( ) );
1753 colorType_ = Lang::ColorInterpolator::GRAY;
1754 break;
1756 catch( const Exceptions::TypeMismatch & )
1761 CMYKcolor_->push_back( Helpers::down_cast< const Lang::CMYK >( piece, callLoc )->components( ) );
1762 colorType_ = Lang::ColorInterpolator::CMYK;
1763 break;
1765 catch( const Exceptions::TypeMismatch & )
1767 throw Exceptions::MiscellaneousRequirement( strrefdup( "Only colors can be passed to an interpolator." ) );
1769 case Lang::ColorInterpolator::RGB:
1770 RGBcolor_->push_back( Helpers::down_cast< const Lang::RGB >( piece, callLoc )->components( ) );
1771 break;
1773 case Lang::ColorInterpolator::GRAY:
1774 graycolor_->push_back( Helpers::down_cast< const Lang::Gray >( piece, callLoc )->components( ) );
1775 break;
1777 case Lang::ColorInterpolator::CMYK:
1778 CMYKcolor_->push_back( Helpers::down_cast< const Lang::CMYK >( piece, callLoc )->components( ) );
1779 break;
1782 else
1784 typedef const Lang::Float ArgType;
1785 double key = Helpers::down_cast< ArgType >( piece, callLoc )->val_;
1786 if( !key_->empty( ) && key < key_->back( ) )
1788 throw Exceptions::MiscellaneousRequirement( strrefdup( "Keys must be added in nondecreasing order to an interpolator." ) );
1790 else
1792 key_->push_back( key );
1796 hasKey_ = ! hasKey_;
1798 Kernel::ContRef cont = evalState->cont_;
1799 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
1800 evalState );
1803 void
1804 Kernel::WarmColorInterpolator::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1806 if( key_->empty( ) )
1808 throw Exceptions::MiscellaneousRequirement( strrefdup( "There are no colors that define the interpolation." ) );
1810 if( hasKey_ )
1812 throw Exceptions::MiscellaneousRequirement( strrefdup( "Missing color for the last key." ) );
1815 Kernel::ContRef cont = evalState->cont_;
1816 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::ColorInterpolator( key_, RGBcolor_, graycolor_, CMYKcolor_, colorType_ ) ),
1817 evalState );
1820 void
1821 Kernel::WarmColorInterpolator::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1823 throw Exceptions::MiscellaneousRequirement( strrefdup( "An interpolator cannot be peeked." ) );
1826 void
1827 Kernel::WarmColorInterpolator::gcMark( Kernel::GCMarkedSet & marked )
1831 namespace Shapes
1833 namespace Kernel
1836 class Mutator_vector_size : public Lang::CoreFunction
1838 public:
1839 Mutator_vector_size( const char * title )
1840 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1843 virtual void
1844 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1846 args.applyDefaults( );
1848 typedef Warm_vector StateType;
1849 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
1851 Kernel::ContRef cont = evalState->cont_;
1852 cont->takeValue( Kernel::ValueRef( new Lang::Integer( state->mem_->size( ) ) ),
1853 evalState );
1857 class Mutator_vector_resize : public Lang::CoreFunction
1859 public:
1860 Mutator_vector_resize( const char * title )
1861 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1863 formals_->appendEvaluatedCoreFormal( "size", Kernel::THE_SLOT_VARIABLE );
1864 formals_->appendEvaluatedCoreFormal( "fill", Kernel::THE_VOID_VARIABLE );
1866 virtual void
1867 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1869 args.applyDefaults( );
1871 typedef const Lang::Integer IndexType;
1872 IndexType::ValueType tmp = Helpers::down_cast_CoreArgument< IndexType >( title_, args, 0, callLoc )->val_;
1873 if( tmp < 0 )
1875 throw Exceptions::CoreOutOfRange( title_, args, 0, "The size must be non-negative." );
1877 size_t newSize = static_cast< size_t >( tmp );
1879 typedef Warm_vector StateType;
1880 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
1882 if( newSize < state->mem_->size( ) )
1884 while( newSize < state->mem_->size( ) )
1886 state->mem_->pop_back( );
1889 else
1891 state->mem_->reserve( newSize );
1892 RefCountPtr< const Lang::Value > fill = args.getValue( 1 );
1893 while( newSize > state->mem_->size( ) )
1895 state->mem_->push_back( fill );
1899 Kernel::ContRef cont = evalState->cont_;
1900 cont->takeValue( Lang::THE_VOID,
1901 evalState );
1905 class Mutator_vector_reserve : public Lang::CoreFunction
1907 public:
1908 Mutator_vector_reserve( const char * title )
1909 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1911 formals_->appendEvaluatedCoreFormal( "size", Kernel::THE_SLOT_VARIABLE );
1913 virtual void
1914 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1916 args.applyDefaults( );
1918 typedef const Lang::Integer IndexType;
1919 IndexType::ValueType tmp = Helpers::down_cast_CoreArgument< IndexType >( title_, args, 0, callLoc )->val_;
1920 if( tmp < 0 )
1922 throw Exceptions::CoreOutOfRange( title_, args, 0, "The size must be non-negative." );
1924 size_t newSize = static_cast< size_t >( tmp );
1926 typedef Warm_vector StateType;
1927 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
1929 state->mem_->reserve( newSize );
1931 Kernel::ContRef cont = evalState->cont_;
1932 cont->takeValue( Lang::THE_VOID,
1933 evalState );
1937 class Mutator_vector_set : public Lang::CoreFunction
1939 public:
1940 Mutator_vector_set( const char * title )
1941 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1943 formals_->appendEvaluatedCoreFormal( "index", Kernel::THE_SLOT_VARIABLE );
1944 formals_->appendEvaluatedCoreFormal( "value", Kernel::THE_SLOT_VARIABLE );
1946 virtual void
1947 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1949 args.applyDefaults( );
1951 typedef Warm_vector StateType;
1952 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
1954 typedef const Lang::Integer IndexType;
1955 IndexType::ValueType tmp = Helpers::down_cast_CoreArgument< IndexType >( title_, args, 0, callLoc )->val_;
1956 if( tmp < 0 )
1958 throw Exceptions::CoreOutOfRange( title_, args, 0, "The index must be non-negative." );
1960 size_t index = static_cast< size_t >( tmp );
1961 if( index >= state->mem_->size( ) )
1963 throw Exceptions::CoreOutOfRange( title_, args, 0, "The index is out of range." );
1966 (*state->mem_)[ index ] = args.getValue( 1 );
1968 Kernel::ContRef cont = evalState->cont_;
1969 cont->takeValue( Lang::THE_VOID,
1970 evalState );
1974 class Mutator_vector_get : public Lang::CoreFunction
1976 public:
1977 Mutator_vector_get( const char * title )
1978 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1980 formals_->appendEvaluatedCoreFormal( "index", Kernel::THE_SLOT_VARIABLE );
1982 virtual void
1983 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1985 args.applyDefaults( );
1987 typedef Warm_vector StateType;
1988 StateType * state = Helpers::mutator_cast_self< StateType >( args.getMutatorSelf( ) );
1990 typedef const Lang::Integer IndexType;
1991 IndexType::ValueType tmp = Helpers::down_cast_CoreArgument< IndexType >( title_, args, 0, callLoc )->val_;
1992 if( tmp < 0 )
1994 throw Exceptions::CoreOutOfRange( title_, args, 0, "The index must be non-negative." );
1996 size_t index = static_cast< size_t >( tmp );
1997 if( index >= state->mem_->size( ) )
1999 throw Exceptions::CoreOutOfRange( title_, args, 0, "The index is out of range." );
2002 Kernel::ContRef cont = evalState->cont_;
2003 cont->takeValue( (*state->mem_)[ index ],
2004 evalState );
2011 Kernel::Warm_vector::Warm_vector( )
2012 : mem_( new std::vector< Kernel::ValueRef > )
2015 Kernel::Warm_vector::~Warm_vector( )
2017 if( mem_ != 0 )
2019 delete mem_;
2023 void
2024 WarmVector_register_mutators( Lang::SystemFinalClass * dstClass )
2026 dstClass->registerMutator( new Kernel::Mutator_vector_size( "size" ) );
2027 dstClass->registerMutator( new Kernel::Mutator_vector_resize( "resize" ) );
2028 dstClass->registerMutator( new Kernel::Mutator_vector_reserve( "reserve" ) );
2029 dstClass->registerMutator( new Kernel::Mutator_vector_set( "set" ) );
2030 dstClass->registerMutator( new Kernel::Mutator_vector_get( "get" ) );
2033 RefCountPtr< const Lang::Class > Kernel::Warm_vector::TypeID( new Lang::SystemFinalClass( strrefdup( "#Array" ), WarmVector_register_mutators ) );
2034 TYPEINFOIMPL_STATE( Warm_vector );
2036 void
2037 Kernel::Warm_vector::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
2039 mem_->push_back( piece );
2040 Kernel::ContRef cont = evalState->cont_;
2041 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
2042 evalState );
2045 void
2046 Kernel::Warm_vector::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
2048 Kernel::ContRef cont = evalState->cont_;
2049 cont->takeValue( Kernel::ValueRef( new Lang::VectorFunction( mem_ ) ),
2050 evalState );
2051 mem_ = 0; /* The VectorFunction owns the memory now. */
2054 void
2055 Kernel::Warm_vector::peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
2057 throw Exceptions::MiscellaneousRequirement( strrefdup( "An array state cannot be peeked. To inspect one entry at at time, use the <get> mutator." ) );
2060 void
2061 Kernel::Warm_vector::gcMark( Kernel::GCMarkedSet & marked )
2065 void
2066 Kernel::registerHot( Kernel::Environment * env )
2068 env->initDefine( Lang::CANVAS_ID, new Kernel::WarmGroup2D );
2069 env->initDefine( Lang::CATALOG_ID, new Kernel::WarmCatalog );
2070 env->initDefine( "stdout", new Kernel::WarmOstream( std::cout ) );
2071 env->initDefine( "stderr", new Kernel::WarmOstream( std::cerr ) );
2072 env->initDefine( "randomdevice", new Kernel::WarmRandomDevice( "/dev/urandom" ) );
2073 env->initDefine( "time", new Kernel::WarmTime );
2074 env->initDefine( "ignore", new Kernel::WarmIgnore );
2076 env->initDefine( "newIgnore", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmIgnore > ) );
2077 env->initDefine( "newGroup", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmGroup2D > ) );
2078 env->initDefine( "newGroup3D", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmGroup3D > ) );
2079 env->initDefine( "newZBuf", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmZBuf > ) );
2080 env->initDefine( "newZSorter", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmZSorter > ) );
2081 env->initDefine( "newString", Kernel::ValueRef( new Lang::HotDefault< Kernel::Warm_ostringstream > ) );
2082 env->initDefine( "newLights", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmGroupLights > ) );
2083 env->initDefine( "newTimer", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmTimer > ) );
2084 env->initDefine( "newText", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmText > ) );
2085 env->initDefine( "newFont", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmType3Font > ) );
2086 env->initDefine( "newColorInterpolator", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmColorInterpolator > ) );
2087 env->initDefine( "newArray", Kernel::ValueRef( new Lang::HotDefault< Kernel::Warm_vector > ) );