Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / hottypes.cc
blob8978e05d4976731585c0fc6898db8815504ecaca
1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * any later version.
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008 Henrik Tidefelt
19 #include "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::BaseFont( ) ), 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 metrics_->horizontalMetrics_ = RefCountPtr< FontMetrics::WritingDirectionMetrics >( new FontMetrics::WritingDirectionMetrics( ) );
987 metrics_->horizontalMetrics_->underlinePosition_ = std::numeric_limits< double >::signaling_NaN( );
988 metrics_->horizontalMetrics_->underlineThickness_ = std::numeric_limits< double >::signaling_NaN( );
989 metrics_->horizontalMetrics_->italicAngleRadians_ = std::numeric_limits< double >::signaling_NaN( );
992 Kernel::WarmType3Font::~WarmType3Font( )
995 RefCountPtr< const Lang::Class > Kernel::WarmType3Font::TypeID( new Lang::SystemFinalClass( strrefdup( "#Type3Font" ) ) );
996 TYPEINFOIMPL_STATE( WarmType3Font );
998 void
999 Kernel::WarmType3Font::tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece,const Ast::SourceLocation & callLoc )
1003 typedef const Lang::Type3Glyph ArgType;
1004 glyphs_.push_back( Helpers::try_cast_CoreArgument< ArgType >( piece ) );
1005 Kernel::ContRef cont = evalState->cont_;
1006 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
1007 evalState );
1008 return;
1010 catch( const NonLocalExit::NotThisType & ball )
1012 /* Wrong type; never mind!.. but see below!
1018 typedef const Lang::KernedText ArgType;
1019 kernings_.push_back( Helpers::try_cast_CoreArgument< ArgType >( piece ) );
1020 Kernel::ContRef cont = evalState->cont_;
1021 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
1022 evalState );
1023 return;
1025 catch( const NonLocalExit::NotThisType & ball )
1027 /* Wrong type; never mind!.. but see below!
1033 typedef const Lang::TaggedValue2D ArgType;
1034 RefCountPtr< ArgType > taggedVal = Helpers::try_cast_CoreArgument< ArgType >( piece );
1036 RefCountPtr< const char > tagMem = Lang::Symbol::nameFromKey( taggedVal->key( ) );
1037 const char * tag = tagMem.getPtr( );
1038 RefCountPtr< const Lang::Value > val = taggedVal->val( );
1040 if( strcmp( tag, "size" ) == 0 )
1042 if( size_ > 0 )
1044 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1046 typedef const Lang::Length ValType;
1047 size_ = Helpers::down_cast< ValType >( val, callLoc )->get( );
1048 if( ! ( size_ > 0 ) )
1050 throw Exceptions::OutOfRange( callLoc, "The size must be positive." );
1053 else if( strcmp( tag, "FontName" ) == 0 )
1055 if( metrics_->fontName_ != NullPtr< const char >( ) )
1057 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1059 typedef const Lang::Symbol ValType;
1060 metrics_->fontName_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1062 else if( strcmp( tag, "FullName" ) == 0 )
1064 if( metrics_->fullName_ != NullPtr< const char >( ) )
1066 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1068 typedef const Lang::String ValType;
1069 metrics_->fullName_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1071 else if( strcmp( tag, "FamilyName" ) == 0 )
1073 if( metrics_->familyName_ != NullPtr< const char >( ) )
1075 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1077 typedef const Lang::Symbol ValType;
1078 metrics_->familyName_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1080 else if( strcmp( tag, "Weight" ) == 0 )
1084 typedef const Lang::Symbol ValType;
1085 RefCountPtr< const char > typedVal = Helpers::try_cast_CoreArgument< ValType >( val )->name( );
1086 if( metrics_->weight_ != NullPtr< const char >( ) )
1088 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1090 static std::set< const char *, charPtrLess > legalStretchValues;
1091 if( legalStretchValues.empty( ) )
1093 initializeLegalStrechValues( & legalStretchValues );
1095 if( legalStretchValues.find( typedVal.getPtr( ) ) == legalStretchValues.end( ) )
1097 throw Exceptions::OutOfRange( callLoc, "The 'Weight value is illegal. Please refer to the PDF specification." );
1099 metrics_->weight_ = typedVal;
1100 goto OK;
1102 catch( const NonLocalExit::NotThisType & ball )
1104 /* Wrong type; never mind!.. but see below!
1110 typedef const Lang::Integer ValType;
1111 RefCountPtr< ValType > casted_val = Helpers::try_cast_CoreArgument< ValType >( val );
1112 if( metrics_->weightNumber_ > 0 )
1114 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1116 if( casted_val->val_ % 100 != 0 )
1118 throw Exceptions::OutOfRange( callLoc, "The 'Weight number must be divisible by 100." );
1120 if( casted_val->val_ < 100 || casted_val->val_ > 900 )
1122 throw Exceptions::OutOfRange( callLoc, "The 'Weight number must be in the range [ 100, 900 ]." );
1124 metrics_->weightNumber_ = casted_val->val_;
1125 goto OK;
1127 catch( const NonLocalExit::NotThisType & ball )
1129 /* Wrong type; never mind!.. but see below!
1133 throw Exceptions::TypeMismatch( callLoc, val->getTypeName( ), Helpers::typeSetString( Lang::String::staticTypeName( ), Lang::Integer::staticTypeName( ) ) );
1135 else if( strcmp( tag, "Version" ) == 0 )
1137 if( metrics_->version_ != NullPtr< const char >( ) )
1139 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1141 typedef const Lang::String ValType;
1142 metrics_->version_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1144 else if( strcmp( tag, "Notice" ) == 0 )
1146 if( metrics_->notice_ != NullPtr< const char >( ) )
1148 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1150 typedef const Lang::String ValType;
1151 metrics_->notice_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1153 else if( strcmp( tag, "EncodingScheme" ) == 0 )
1155 if( metrics_->encodingScheme_ != NullPtr< const char >( ) )
1157 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1159 typedef const Lang::Symbol ValType;
1160 metrics_->encodingScheme_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1162 else if( strcmp( tag, "CharacterSet" ) == 0 )
1164 if( metrics_->characterSet_ != NullPtr< const char >( ) )
1166 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1168 typedef const Lang::Symbol ValType;
1169 metrics_->characterSet_ = Helpers::down_cast< ValType >( val, callLoc )->name( );
1171 else if( strcmp( tag, "Comment" ) == 0 )
1173 typedef const Lang::String ValType;
1174 RefCountPtr< ValType > typedVal = Helpers::down_cast< ValType >( val, callLoc );
1175 metrics_->comments_.push_back( FontMetrics::AFM::AssortedInfo( tagMem, typedVal->val_ ) );
1177 else if( strcmp( tag, "CapHeight" ) == 0 )
1179 if( ! IS_NAN( metrics_->capHeight_ ) )
1181 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1183 if( ! ( size_ > 0 ) )
1185 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1187 typedef const Lang::Length ValType;
1188 metrics_->capHeight_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1190 else if( strcmp( tag, "XHeight" ) == 0 )
1192 if( ! IS_NAN( metrics_->xHeight_ ) )
1194 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1196 if( ! ( size_ > 0 ) )
1198 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1200 typedef const Lang::Length ValType;
1201 metrics_->xHeight_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1203 else if( strcmp( tag, "Ascent" ) == 0 )
1205 if( ! IS_NAN( metrics_->ascender_ ) )
1207 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1209 if( ! ( size_ > 0 ) )
1211 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1213 typedef const Lang::Length ValType;
1214 metrics_->ascender_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1216 else if( strcmp( tag, "Descent" ) == 0 )
1218 if( ! IS_NAN( metrics_->descender_ ) )
1220 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1222 if( ! ( size_ > 0 ) )
1224 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1226 typedef const Lang::Length ValType;
1227 metrics_->descender_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1229 else if( strcmp( tag, "Leading" ) == 0 )
1231 if( ! IS_NAN( metrics_->leading_ ) )
1233 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1235 if( ! ( size_ > 0 ) )
1237 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1239 typedef const Lang::Length ValType;
1240 metrics_->leading_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1242 else if( strcmp( tag, "StemH" ) == 0 )
1244 if( ! IS_NAN( metrics_->stdHW_ ) )
1246 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1248 if( ! ( size_ > 0 ) )
1250 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1252 typedef const Lang::Length ValType;
1253 metrics_->stdHW_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1255 else if( strcmp( tag, "StemV" ) == 0 )
1257 if( ! IS_NAN( metrics_->stdVW_ ) )
1259 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1261 if( ! ( size_ > 0 ) )
1263 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1265 typedef const Lang::Length ValType;
1266 metrics_->stdVW_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1268 else if( strcmp( tag, "FontBBox" ) == 0 )
1270 if( metrics_->fontBBoxXMax_ >= metrics_->fontBBoxXMin_ )
1272 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1274 if( ! ( size_ > 0 ) )
1276 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1278 typedef const Lang::ElementaryPath2D ValType;
1279 RefCountPtr< ValType > casted_val = Helpers::elementaryPathTry2D( val );
1280 Concrete::Coords2D llcorner( 0, 0 );
1281 Concrete::Coords2D urcorner( 0, 0 );
1282 if( ! casted_val->boundingRectangle( & llcorner, & urcorner ) )
1284 throw Exceptions::OutOfRange( callLoc, "The path was empty." );
1286 metrics_->fontBBoxXMin_ = llcorner.x_ / size_;
1287 metrics_->fontBBoxYMin_ = llcorner.y_ / size_;
1288 metrics_->fontBBoxXMax_ = urcorner.x_ / size_;
1289 metrics_->fontBBoxYMax_ = urcorner.y_ / size_;
1291 else if( strcmp( tag, "UnderlinePosition" ) == 0 )
1293 if( ! IS_NAN( metrics_->horizontalMetrics_->underlinePosition_ ) )
1295 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1297 if( ! ( size_ > 0 ) )
1299 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1301 typedef const Lang::Length ValType;
1302 metrics_->horizontalMetrics_->underlinePosition_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1304 else if( strcmp( tag, "UnderlineThickness" ) == 0 )
1306 if( ! IS_NAN( metrics_->horizontalMetrics_->underlineThickness_ ) )
1308 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1310 if( ! ( size_ > 0 ) )
1312 throw Exceptions::OutOfRange( callLoc, "Please provide a value for 'size first." );
1314 typedef const Lang::Length ValType;
1315 metrics_->horizontalMetrics_->underlineThickness_ = Helpers::down_cast< ValType >( val, callLoc )->get( ) / size_;
1317 else if( strcmp( tag, "ItalicAngle" ) == 0 )
1319 if( ! IS_NAN( metrics_->horizontalMetrics_->italicAngleRadians_ ) )
1321 throw Exceptions::MiscellaneousRequirement( "Multiply specified value." );
1323 typedef const Lang::Float ValType;
1324 metrics_->horizontalMetrics_->italicAngleRadians_ = Helpers::down_cast< ValType >( val, callLoc )->val_;
1326 else
1328 typedef const Lang::String ValType;
1329 RefCountPtr< ValType > typedVal = Helpers::down_cast< ValType >( val, callLoc );
1330 metrics_->assortedGlobalInfo_.push_back( FontMetrics::AFM::AssortedInfo( tagMem, typedVal->val_ ) );
1334 Kernel::ContRef cont = evalState->cont_;
1335 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
1336 evalState );
1337 return;
1339 catch( const NonLocalExit::NotThisType & ball )
1341 /* Wrong type; never mind!.. but see below!
1345 throw Exceptions::TypeMismatch( callLoc, piece->getTypeName( ), Helpers::typeSetString( Lang::Type3Glyph::staticTypeName( ), Lang::KernedText::staticTypeName( ), Lang::TaggedValue2D::staticTypeName( ) ) );
1348 void
1349 Kernel::WarmType3Font::freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
1351 if( glyphs_.empty( ) )
1353 throw Exceptions::OutOfRange( callLoc, "A font without glyphs?!" );
1355 if( ! ( size_ > 0 ) )
1357 throw Exceptions::OutOfRange( callLoc, "Missing 'size." );
1359 if( strlen( metrics_->fontName_.getPtr( ) ) == 0 )
1361 throw Exceptions::OutOfRange( callLoc, "Missing 'FontName." );
1363 if( metrics_->weightNumber_ == 0 )
1365 metrics_->weightNumber_ = 400;
1367 bool findBBox = false;
1368 if( metrics_->fontBBoxXMax_ < metrics_->fontBBoxXMin_ )
1370 findBBox = true;
1373 Concrete::ReciprocalLength invSize = 1 / size_;
1375 metrics_->charCount_ = glyphs_.size( );
1376 metrics_->isCIDFont_ = false;
1378 size_t firstChar = INT_MAX;
1379 size_t lastChar = 0;
1381 // In the first scan of the glyphs, only firstChar and lastChar are computed. The other tasks are performed in the later scan.
1382 typedef typeof glyphs_ ListType;
1383 for( ListType::const_iterator i = glyphs_.begin( ); i != glyphs_.end( ); ++i )
1385 size_t code = (*i)->code( );
1386 if( code > 0 )
1388 firstChar = std::min( firstChar, code );
1389 lastChar = std::max( lastChar, code );
1394 RefCountPtr< SimplePDF::PDF_Vector > widths;
1396 RefCountPtr< SimplePDF::PDF_Object > stdWidth = SimplePDF::newFloat( 0 );
1397 widths->vec.resize( lastChar - firstChar + 1, stdWidth );
1399 RefCountPtr< SimplePDF::PDF_Dictionary > charProcs;
1400 RefCountPtr< SimplePDF::PDF_Resources > resources;
1401 // RefCountPtr< SimplePDF::PDF_Stream_out > toUnicode;
1403 RefCountPtr< FontMetrics::WritingDirectionMetrics > horizontal = metrics_->horizontalMetrics_;
1404 horizontal->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 = horizontal->charData_.size( );
1422 FontMetrics::CharacterMetrics * glyphMetrics = new FontMetrics::CharacterMetrics( pos );
1423 (*i)->setupMetric( glyphMetrics, invSize );
1424 horizontal->charData_.push_back( glyphMetrics );
1425 horizontal->nameMap_[ (*i)->name( ) ] = pos;
1426 if( code > 0 )
1428 horizontal->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( horizontal->italicAngleRadians_ ) )
1461 (*fontDescriptor)[ "ItalicAngle" ] = SimplePDF::newFloat( ( 180 / M_PI ) * horizontal->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::Font( 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 )
1832 void
1833 Kernel::registerHot( Kernel::Environment * env )
1835 env->initDefine( Lang::CANVAS_ID, new Kernel::WarmGroup2D );
1836 env->initDefine( Lang::CATALOG_ID, new Kernel::WarmCatalog );
1837 env->initDefine( "stdout", new Kernel::WarmOstream( std::cout ) );
1838 env->initDefine( "stderr", new Kernel::WarmOstream( std::cerr ) );
1839 env->initDefine( "randomdevice", new Kernel::WarmRandomDevice( "/dev/urandom" ) );
1840 env->initDefine( "time", new Kernel::WarmTime );
1841 env->initDefine( "ignore", new Kernel::WarmIgnore );
1843 env->initDefine( "newIgnore", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmIgnore > ) );
1844 env->initDefine( "newGroup", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmGroup2D > ) );
1845 env->initDefine( "newGroup3D", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmGroup3D > ) );
1846 env->initDefine( "newZBuf", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmZBuf > ) );
1847 env->initDefine( "newZSorter", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmZSorter > ) );
1848 env->initDefine( "newString", Kernel::ValueRef( new Lang::HotDefault< Kernel::Warm_ostringstream > ) );
1849 env->initDefine( "newLights", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmGroupLights > ) );
1850 env->initDefine( "newTimer", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmTimer > ) );
1851 env->initDefine( "newText", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmText > ) );
1852 env->initDefine( "newFont", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmType3Font > ) );
1853 env->initDefine( "newColorInterpolator", Kernel::ValueRef( new Lang::HotDefault< Kernel::WarmColorInterpolator > ) );