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
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"
23 #include "continuations.h"
24 #include "texttypes.h"
25 #include "fontmetrics.h"
28 #include "pdfstructure.h"
29 #include "timetypes.h"
30 #include "shapescore.h"
34 #include <sys/resource.h>
38 using namespace Shapes
;
41 Lang::Hot::Hot::Hot( )
47 RefCountPtr
< const Lang::Class
> Lang::Hot::TypeID( new Lang::SystemFinalClass( strrefdup( "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
)
55 Lang::HotTriple::~HotTriple( )
59 Lang::HotTriple::newState( ) const
61 return new Kernel::WarmTriple( init_
, update_
, result_
);
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_
);
82 Lang::HotRandomSeed::HotRandomSeed( size_t sz
, unsigned long seed
)
83 : sz_( sz
), state_( new char[ sz
] )
85 char * oldState
= initstate( seed
, state_
, sz_
);
89 Lang::HotRandomSeed::~HotRandomSeed( )
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.
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
);
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_
,
127 update_
->call( evalState
, pile_
, piece
, callLoc
);
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
);
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
);
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
);
165 Kernel::WarmIgnore::tackOnImpl( Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Value
> & piece
,const Ast::SourceLocation
& callLoc
)
169 Kernel::ContRef cont
= evalState
->cont_
;
170 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
175 Kernel::WarmIgnore::freezeImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
177 throw Exceptions::MiscellaneousRequirement( strrefdup( "An ignore state cannot be frozen." ) );
181 Kernel::WarmIgnore::peekImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
183 throw Exceptions::MiscellaneousRequirement( strrefdup( "An ignore state cannot be peeked." ) );
187 Kernel::WarmIgnore::gcMark( Kernel::GCMarkedSet
& marked
)
191 Kernel::WarmOstream::WarmOstream( std::ostream
& os
)
195 Kernel::WarmOstream::~WarmOstream( )
198 RefCountPtr
< const Lang::Class
> Kernel::WarmOstream::TypeID( new Lang::SystemFinalClass( strrefdup( "#OutputStream" ) ) );
199 TYPEINFOIMPL_STATE( WarmOstream
);
202 Kernel::WarmOstream::tackOnImpl( Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Value
> & piece
,const Ast::SourceLocation
& callLoc
)
205 Kernel::ContRef cont
= evalState
->cont_
;
206 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
211 Kernel::WarmOstream::freezeImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
213 throw Exceptions::MiscellaneousRequirement( strrefdup( "A warm ostream cannot be frozen." ) );
217 Kernel::WarmOstream::peekImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
219 throw Exceptions::MiscellaneousRequirement( strrefdup( "A warm ostream cannot be peeked." ) );
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
);
237 Kernel::Warm_ostringstream::tackOnImpl( Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Value
> & piece
,const Ast::SourceLocation
& callLoc
)
240 Kernel::ContRef cont
= evalState
->cont_
;
241 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
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( ) ) ) ),
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( ) ) ) ),
262 Kernel::Warm_ostringstream::gcMark( Kernel::GCMarkedSet
& marked
)
271 class Mutator_erase
: public Lang::CoreFunction
274 Mutator_erase( const char * title
)
275 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
279 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
281 args
.applyDefaults( );
284 StateType
* state
= Helpers::mutator_cast_self
< StateType
>( args
.getMutatorSelf( ) );
287 Kernel::ContRef cont
= evalState
->cont_
;
288 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
294 class Mutator_remove
: public Lang::CoreFunction
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
);
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
);
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
,
324 Kernel::WarmGroup2D::WarmGroup2D( )
325 : pile_( Lang::THE_NULL2D
)
328 Kernel::WarmGroup2D::~WarmGroup2D( )
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
);
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( ) );
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
,
364 evalState
->dyn_
->getGraphicsState( ) ) );
365 Kernel::ContRef cont
= evalState
->cont_
;
366 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
371 Kernel::WarmGroup2D::freezeImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
373 Kernel::ContRef cont
= evalState
->cont_
;
374 cont
->takeValue( pile_
,
379 Kernel::WarmGroup2D::peekImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
381 Kernel::ContRef cont
= evalState
->cont_
;
382 cont
->takeValue( pile_
,
387 Kernel::WarmGroup2D::erase( )
389 pile_
= Lang::THE_NULL2D
;
393 Kernel::WarmGroup2D::remove( Lang::Symbol::KeyType key
)
395 pile_
= pile_
->removeShallow( key
);
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( )
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
);
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
),
428 evalState
->dyn_
->getGraphicsState( ) ) );
429 Kernel::ContRef cont
= evalState
->cont_
;
430 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
435 Kernel::WarmGroup3D::freezeImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
437 Kernel::ContRef cont
= evalState
->cont_
;
438 cont
->takeValue( pile_
,
443 Kernel::WarmGroup3D::peekImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
445 Kernel::ContRef cont
= evalState
->cont_
;
446 cont
->takeValue( pile_
,
451 Kernel::WarmGroup3D::erase( )
453 pile_
= Lang::THE_NULL3D
;
457 Kernel::WarmGroup3D::remove( Lang::Symbol::KeyType key
)
459 pile_
= pile_
->removeShallow( key
);
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
);
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
),
484 Kernel::ContRef cont
= evalState
->cont_
;
485 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
490 Kernel::WarmGroupLights::freezeImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
492 Kernel::ContRef cont
= evalState
->cont_
;
493 cont
->takeValue( pile_
,
498 Kernel::WarmGroupLights::peekImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
500 Kernel::ContRef cont
= evalState
->cont_
;
501 cont
->takeValue( pile_
,
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
);
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
,
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
,
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( ) );
576 Kernel::ContRef cont
= evalState
->cont_
;
577 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
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( ) ) );
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( ) ) ),
599 Kernel::WarmZBuf::peekImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
601 throw Exceptions::MiscellaneousRequirement( strrefdup( "A z-buffer state cannot be peeked." ) );
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
);
615 // typedef typeof *strokePile_ ListType;
616 // for( ListType::const_iterator i = strokePile_->begin( ); i != strokePile_->end( ); ++i )
618 // const_cast< Computation::StrokedLine3D * >( i->getPtr( ) )->gcMark( marked );
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
);
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
,
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
,
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( ) );
695 Kernel::ContRef cont
= evalState
->cont_
;
696 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
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( ) ) );
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( ) ) ),
718 Kernel::WarmZSorter::peekImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
720 throw Exceptions::MiscellaneousRequirement( strrefdup( "A z-sorter state cannot be peeked." ) );
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
);
734 // typedef typeof *strokePile_ ListType;
735 // for( ListType::const_iterator i = strokePile_->begin( ); i != strokePile_->end( ); ++i )
737 // const_cast< Computation::StrokedLine3D * >( i->getPtr( ) )->gcMark( marked );
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( )
753 int res
= getrusage( RUSAGE_SELF
, &ru
);
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
);
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." ) );
774 Kernel::WarmTimer::freezeImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
777 int res
= getrusage( RUSAGE_SELF
, &ru
);
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
) ),
792 Kernel::WarmTimer::peekImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
795 int res
= getrusage( RUSAGE_SELF
, &ru
);
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
) ),
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
);
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
,
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
,
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
,
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
,
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
,
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( ) ) );
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
,
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
) );
948 Kernel::ContRef cont
= evalState
->cont_
;
949 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::Text( evalState
->dyn_
->getGraphicsState( ),
950 evalState
->dyn_
->getTextState( ),
952 RefCountPtr
< const Lang::ElementaryPath2D
>( bbox
) ) ),
957 Kernel::WarmText::peekImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
959 throw Exceptions::MiscellaneousRequirement( strrefdup( "A text graphics state cannot be peeked." ) );
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
);
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
,
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
,
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 )
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
;
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_
;
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_
;
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
,
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( ) ) );
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_
)
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( );
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( );
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
;
1428 horizontal
->codeMap_
[ code
] = pos
;
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_
);
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
);
1513 // static bool shown = false;
1516 // std::cerr << "Warning: The ToUnicode CMap is not setup by Shapes." << std::endl ;
1520 // (*dic)[ "ToUnicode" ] = toUnicode;
1522 Kernel::ContRef cont
= evalState
->cont_
;
1523 cont
->takeValue( Kernel::ValueRef( new Lang::Font( metrics_
->fontName_
,
1530 Kernel::WarmType3Font::peekImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
1532 throw Exceptions::MiscellaneousRequirement( strrefdup( "A type 3 font state cannot be peeked." ) );
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
);
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
);
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
);
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
,
1614 Kernel::WarmRandomDevice::freezeImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
1616 throw Exceptions::MiscellaneousRequirement( strrefdup( "The random device cannot be frozen." ) );
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." ) ) );
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
) ),
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
);
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." ) );
1659 Kernel::WarmTime::freezeImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
1661 throw Exceptions::MiscellaneousRequirement( strrefdup( "The time cannot be frozen." ) );
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
) ),
1674 Kernel::WarmTime::gcMark( Kernel::GCMarkedSet
& marked
)
1678 Kernel::WarmRandomState::WarmRandomState( char * 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
);
1691 Kernel::WarmRandomState::setState( )
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." ) );
1703 Kernel::WarmRandomState::freezeImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
1705 throw Exceptions::MiscellaneousRequirement( strrefdup( "A random state cannot be frozen." ) );
1709 Kernel::WarmRandomState::peekImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
1712 long tmp
= random( );
1713 Kernel::ContRef cont
= evalState
->cont_
;
1714 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::Integer( tmp
) ),
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
);
1734 Kernel::WarmColorInterpolator::tackOnImpl( Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Value
> & piece
,const Ast::SourceLocation
& callLoc
)
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
;
1747 catch( const Exceptions::TypeMismatch
& )
1752 graycolor_
->push_back( Helpers::down_cast
< const Lang::Gray
>( piece
, callLoc
)->components( ) );
1753 colorType_
= Lang::ColorInterpolator::GRAY
;
1756 catch( const Exceptions::TypeMismatch
& )
1761 CMYKcolor_
->push_back( Helpers::down_cast
< const Lang::CMYK
>( piece
, callLoc
)->components( ) );
1762 colorType_
= Lang::ColorInterpolator::CMYK
;
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( ) );
1773 case Lang::ColorInterpolator::GRAY
:
1774 graycolor_
->push_back( Helpers::down_cast
< const Lang::Gray
>( piece
, callLoc
)->components( ) );
1777 case Lang::ColorInterpolator::CMYK
:
1778 CMYKcolor_
->push_back( Helpers::down_cast
< const Lang::CMYK
>( piece
, callLoc
)->components( ) );
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." ) );
1792 key_
->push_back( key
);
1796 hasKey_
= ! hasKey_
;
1798 Kernel::ContRef cont
= evalState
->cont_
;
1799 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
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." ) );
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_
) ),
1821 Kernel::WarmColorInterpolator::peekImpl( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
1823 throw Exceptions::MiscellaneousRequirement( strrefdup( "An interpolator cannot be peeked." ) );
1827 Kernel::WarmColorInterpolator::gcMark( Kernel::GCMarkedSet
& marked
)
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
> ) );