Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / coreconstruct.cc
blob4c1c14601b856f05c0cba99c4fe4957c3603df1a
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 <cmath>
21 #include "Shapes_Helpers_decls.h"
23 #include "shapescore.h"
24 #include "globals.h"
25 #include "shapesexceptions.h"
26 #include "consts.h"
27 #include "simplepdfi.h"
28 #include "simplepdfo.h"
29 #include "astfun.h"
30 #include "tagtypes.h"
31 #include "multipage.h"
32 #include "charconverters.h"
33 #include "pagecontentstates.h"
34 #include "texlabelmanager.h"
35 #include "autoonoff.h"
36 #include "timetypes.h"
37 #include "config.h"
39 #include <iostream>
40 #include <sstream>
41 #include <fstream>
42 #include <vector>
43 #include <stdio.h>
44 #include <ctime>
46 using namespace Shapes;
49 namespace Shapes
51 namespace Lang
54 class Core_tag : public Lang::CoreFunction
56 public:
57 Core_tag( const char * title )
58 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
60 formals_->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE );
61 formals_->appendEvaluatedCoreFormal( "obj", Kernel::THE_SLOT_VARIABLE );
62 formals_->appendEvaluatedCoreFormal( "transform", Kernel::THE_TRUE_VARIABLE ); // this argument means "transform if applicable"
63 formals_->appendEvaluatedCoreFormal( "draw", Kernel::THE_TRUE_VARIABLE ); // this argument means "draw if applicable"
66 virtual void
67 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
69 args.applyDefaults( );
71 typedef const Lang::Symbol KeyType;
72 RefCountPtr< KeyType > key = Helpers::down_cast_CoreArgument< KeyType >( title_, args, 0, callLoc );
73 bool tryTransform = Helpers::down_cast_CoreArgument< const Lang::Boolean >( title_, args, 2, callLoc )->val_;
74 bool tryDraw = Helpers::down_cast_CoreArgument< const Lang::Boolean >( title_, args, 3, callLoc )->val_;
76 if( tryDraw && ! tryTransform )
78 throw Exceptions::CoreOutOfRange( title_, args, 3, "A tagged object which does not transform cannot be drawn." );
81 size_t argsi = 1;
83 if( tryDraw )
85 try
87 typedef const Lang::Drawable2D ArgType;
89 RefCountPtr< ArgType > obj = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( argsi ) );
91 Kernel::ContRef cont = evalState->cont_;
92 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::TaggedDrawable2D( key, obj ) ),
93 evalState );
94 return;
96 catch( const NonLocalExit::NotThisType & ball )
98 // Never mind, see below
103 typedef const Lang::Drawable3D ArgType;
105 RefCountPtr< ArgType > obj = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( argsi ) );
107 Kernel::ContRef cont = evalState->cont_;
108 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::TaggedDrawable3D( key, obj ) ),
109 evalState );
110 return;
112 catch( const NonLocalExit::NotThisType & ball )
114 // Never mind, see below
118 if( tryTransform )
122 typedef const Lang::Geometric2D ArgType;
124 RefCountPtr< ArgType > obj = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( argsi ) );
126 Kernel::ContRef cont = evalState->cont_;
127 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::TaggedGeometric2D( key, obj ) ),
128 evalState );
129 return;
131 catch( const NonLocalExit::NotThisType & ball )
133 // Never mind, see below
138 typedef const Lang::Geometric3D ArgType;
140 RefCountPtr< ArgType > obj = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( argsi ) );
142 Kernel::ContRef cont = evalState->cont_;
143 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::TaggedGeometric3D( key, obj ) ),
144 evalState );
145 return;
147 catch( const NonLocalExit::NotThisType & ball )
149 // Never mind, see below
154 // As a last resort, we tag any value.
155 // We return a Drawable2D. Use immerse to make it 3D.
156 Kernel::ContRef cont = evalState->cont_;
157 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::TaggedValue2D( key, args.getValue( argsi ) ) ),
158 evalState );
163 // This function is in this file just because it i so related to Core_tag.
164 class Core_find : public Lang::CoreFunction
166 public:
167 Core_find( const char * title )
168 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
170 formals_->appendEvaluatedCoreFormal( "container", Kernel::THE_SLOT_VARIABLE );
171 formals_->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE );
174 virtual void
175 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
177 args.applyDefaults( );
179 typedef const Lang::Symbol KeyType;
180 RefCountPtr< KeyType > key = Helpers::down_cast_CoreArgument< KeyType >( title_, args, 1, callLoc );
182 size_t argsi = 0;
186 typedef const Lang::Drawable2D ContainerType;
188 RefCountPtr< ContainerType > container = Helpers::try_cast_CoreArgument< ContainerType >( args.getValue( argsi ) );
190 if( ! container->findOneTag( evalState, key->getKey( ), Lang::THE_2D_IDENTITY ) )
192 throw Exceptions::CoreOutOfRange( title_, args, 1, "Key not found." );
194 return;
196 catch( const NonLocalExit::NotThisType & ball )
198 // Never mind, see below
203 typedef const Lang::Drawable3D ContainerType;
205 RefCountPtr< ContainerType > container = Helpers::try_cast_CoreArgument< ContainerType >( args.getValue( argsi ) );
207 if( ! container->findOneTag( evalState, key->getKey( ), Lang::THE_3D_IDENTITY ) )
209 throw Exceptions::CoreOutOfRange( title_, args, 1, "Key not found." );
211 return;
213 catch( const NonLocalExit::NotThisType & ball )
215 // Never mind, see below
218 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, argsi, Helpers::typeSetString( Lang::Drawable2D::staticTypeName( ), Lang::Drawable3D::staticTypeName( ) ) );
222 // This function is in this file just because it i so related to Core_tag.
223 class Core_findall : public Lang::CoreFunction
225 public:
226 Core_findall( const char * title )
227 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
229 formals_->appendEvaluatedCoreFormal( "container", Kernel::THE_SLOT_VARIABLE );
230 formals_->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE );
233 virtual void
234 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
236 args.applyDefaults( );
238 typedef const Lang::Symbol KeyType;
239 RefCountPtr< KeyType > key = Helpers::down_cast_CoreArgument< KeyType >( title_, args, 1, callLoc );
241 size_t argsi = 0;
245 typedef const Lang::Drawable2D ContainerType;
247 RefCountPtr< ContainerType > container = Helpers::try_cast_CoreArgument< ContainerType >( args.getValue( argsi ) );
249 std::vector< Kernel::ValueRef > * dst = new std::vector< Kernel::ValueRef >;
250 container->findTags( dst, evalState->dyn_, key->getKey( ), Lang::THE_2D_IDENTITY );
252 Kernel::ContRef cont = evalState->cont_;
253 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::VectorFunction( dst ) ),
254 evalState );
255 return;
257 catch( const NonLocalExit::NotThisType & ball )
259 // Never mind, see below
264 typedef const Lang::Drawable3D ContainerType;
266 RefCountPtr< ContainerType > container = Helpers::try_cast_CoreArgument< ContainerType >( args.getValue( argsi ) );
268 std::vector< Kernel::ValueRef > * dst = new std::vector< Kernel::ValueRef >;
269 container->findTags( dst, evalState->dyn_, key->getKey( ), Lang::THE_3D_IDENTITY );
271 Kernel::ContRef cont = evalState->cont_;
272 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::VectorFunction( dst ) ),
273 evalState );
274 return;
276 catch( const NonLocalExit::NotThisType & ball )
278 // Never mind, see below
281 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, argsi, Helpers::typeSetString( Lang::Drawable2D::staticTypeName( ), Lang::Drawable3D::staticTypeName( ) ) );
285 class Core_phong : public Lang::CoreFunction
287 public:
288 Core_phong( const char * title ) : CoreFunction( title ) { }
289 virtual void
290 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
292 const size_t ARITY = 1;
293 CHECK_ARITY( args, ARITY, title_ );
295 typedef const Lang::Float ArgType;
296 double exponent = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc )->val_;
297 if( exponent < 0 )
299 throw Exceptions::CoreOutOfRange( title_, args, 0, "The Phong exponent should be greater than 0." );
302 Kernel::ContRef cont = evalState->cont_;
303 cont->takeValue( Kernel::ValueRef( new Lang::SpecularReflectionTerm( 1., exponent ) ),
304 evalState );
308 class Core_cons : public Lang::CoreFunction
310 public:
311 Core_cons( const char * title )
312 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), false ) )
314 formals_->appendEvaluatedCoreFormal( "car", Kernel::THE_SLOT_VARIABLE );
315 formals_->appendEvaluatedCoreFormal( "cdr", Kernel::THE_SLOT_VARIABLE );
317 virtual void
318 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
320 const size_t ARITY = 2;
321 CHECK_ARITY( args, ARITY, title_ );
323 Kernel::ContRef cont = evalState->cont_;
324 cont->takeValue( Kernel::ValueRef( new Lang::ConsPair( args.getHandle( 0 ),
325 args.getHandle( 1 ) ) ),
326 evalState );
330 class Core_list : public Lang::CoreFunction
332 public:
333 Core_list( const char * title ) : CoreFunction( title ) { }
334 virtual void
335 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
337 RefCountPtr< const Lang::SingleList > res = Lang::THE_CONS_NULL;
338 if( ! args.empty( ) )
340 for( size_t i = args.size( ) - 1; ; --i )
342 res = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( args.getHandle( i ), res ) );
343 if( i == 0 )
345 break;
350 Kernel::ContRef cont = evalState->cont_;
351 cont->takeValue( res,
352 evalState );
356 class Core_unlist : public Lang::CoreFunction
358 Kernel::UnnamedStructureFactory argListFactory_;
359 public:
360 Core_unlist( const char * title ) : CoreFunction( title ) { }
361 virtual void
362 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
364 const size_t ARITY = 1;
365 CHECK_ARITY( args, ARITY, title_ );
367 typedef const Lang::SingleList ArgType;
369 Kernel::ContRef cont = evalState->cont_;
370 cont->takeValue( argListFactory_.build( Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc ) ),
371 evalState );
375 class Core_isnull : public Lang::CoreFunction
377 public:
378 Core_isnull( const char * title ) : CoreFunction( title ) { }
379 virtual void
380 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
382 const size_t ARITY = 1;
383 CHECK_ARITY( args, ARITY, title_ );
385 RefCountPtr< const Lang::Value > aUntyped = args.getValue( 0 );
387 Kernel::ContRef cont = evalState->cont_;
388 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::Boolean( dynamic_cast< const Lang::SingleListNull * >( args.getValue( 0 ).getPtr( ) ) != 0 ) ),
389 evalState );
393 class Core_range : public Lang::CoreFunction
395 public:
396 Core_range( const char * title )
397 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
399 formals_->appendEvaluatedCoreFormal( "begin", Kernel::THE_VOID_VARIABLE );
400 formals_->appendEvaluatedCoreFormal( "end", Kernel::THE_VOID_VARIABLE );
401 formals_->appendEvaluatedCoreFormal( "step", Kernel::THE_VOID_VARIABLE );
402 formals_->appendEvaluatedCoreFormal( "count", Kernel::THE_VOID_VARIABLE );
404 virtual void
405 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
407 typedef const Lang::Integer CountType;
409 args.applyDefaults( );
413 typedef const Lang::Integer ArgType;
415 RefCountPtr< ArgType > beginPtr = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ), true );
416 RefCountPtr< ArgType > endPtr = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 1 ), true );
417 if( beginPtr == NullPtr< ArgType >( ) && endPtr == NullPtr< ArgType >( ) )
419 throw Exceptions::CoreRequirement( "At least one of the arguments <begin> and <end> must be provided.", title_, callLoc );
421 RefCountPtr< ArgType > stepPtr = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 2, callLoc, true );
422 RefCountPtr< CountType > countPtr = Helpers::down_cast_CoreArgument< CountType >( title_, args, 3, callLoc, true );
424 if( beginPtr != NullPtr< ArgType >( ) && endPtr != NullPtr< ArgType >( ) &&
425 stepPtr != NullPtr< ArgType >( ) && countPtr != NullPtr< CountType >( ) )
427 throw Exceptions::CoreRequirement( "At least one of the arguments must be omitted.", title_, callLoc );
430 ArgType::ValueType begin = 0;
431 ArgType::ValueType end = -1;
432 ArgType::ValueType step = 1;
433 if( beginPtr == NullPtr< ArgType >( ) )
435 if( stepPtr != NullPtr< ArgType >( ) )
437 step = stepPtr->val_;
439 if( countPtr == NullPtr< CountType >( ) )
441 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of integers when <begin> is omitted.", title_, callLoc );
443 if( countPtr->val_ < 2 )
445 throw Exceptions::CoreOutOfRange( title_, args, 3, "The <count> must be at least 2." );
447 end = endPtr->val_;
448 begin = end - step * ( countPtr->val_ - 1 );
450 else if( endPtr == NullPtr< ArgType >( ) )
452 if( stepPtr != NullPtr< ArgType >( ) )
454 step = stepPtr->val_;
456 if( countPtr == NullPtr< CountType >( ) )
458 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of integers when <end> is omitted.", title_, callLoc );
460 if( countPtr->val_ < 2 )
462 throw Exceptions::CoreOutOfRange( title_, args, 3, "The <count> must be at least 2." );
464 begin = beginPtr->val_;
465 end = begin + step * ( countPtr->val_ - 1 );
467 else
469 if( countPtr != NullPtr< CountType >( ) )
471 throw Exceptions::CoreRequirement( "It is an error to provide the <count> arguments when constructing a range of integers from <begin> to <end>.", title_, args.getLoc( 3 ) );
474 begin = beginPtr->val_;
475 end = endPtr->val_;
476 if( stepPtr != NullPtr< ArgType >( ) )
478 step = stepPtr->val_;
482 std::list< ArgType::ValueType > tmp;
484 RefCountPtr< const Lang::SingleList > res = Lang::THE_CONS_NULL;
485 if( step > 0 )
487 for( ArgType::ValueType x = begin; x <= end; x += step )
489 tmp.push_back( x );
492 else if( step < 0 )
494 for( ArgType::ValueType x = begin; x >= end; x += step )
496 tmp.push_back( x );
499 else
501 throw Exceptions::CoreOutOfRange( title_, args, 2, "Step size must not be zero." );
504 while( ! tmp.empty( ) )
506 res = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( Helpers::newValHandle( new Lang::Integer( tmp.back( ) ) ),
507 res ) );
508 tmp.pop_back( );
511 Kernel::ContRef cont = evalState->cont_;
512 cont->takeValue( res,
513 evalState );
514 return;
516 catch( const NonLocalExit::NotThisType & ball )
518 // Never mind, see below
523 typedef const Lang::Float ArgType;
525 RefCountPtr< ArgType > beginPtr = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ), true );
526 RefCountPtr< ArgType > endPtr = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 1 ), true );
527 if( beginPtr == NullPtr< ArgType >( ) && endPtr == NullPtr< ArgType >( ) )
529 throw Exceptions::CoreRequirement( "At least one of the arguments <begin> and <end> must be provided.", title_, callLoc );
531 RefCountPtr< ArgType > stepPtr = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 2, callLoc, true );
532 RefCountPtr< CountType > countPtr = Helpers::down_cast_CoreArgument< CountType >( title_, args, 3, callLoc, true );
534 if( beginPtr != NullPtr< ArgType >( ) && endPtr != NullPtr< ArgType >( ) &&
535 stepPtr != NullPtr< ArgType >( ) && countPtr != NullPtr< CountType >( ) )
537 throw Exceptions::CoreRequirement( "At least one of the arguments must be omitted.", title_, callLoc );
540 double begin = 0;
541 double end = -1;
542 double step = 1;
543 bool appendEnd = false;
544 if( beginPtr == NullPtr< ArgType >( ) )
546 if( stepPtr == NullPtr< ArgType >( ) )
548 throw Exceptions::CoreRequirement( "The <step> must be provided when constructing a range of floats when <begin> is omitted.", title_, callLoc );
550 if( countPtr == NullPtr< CountType >( ) )
552 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of floats when <begin> is omitted.", title_, callLoc );
554 if( countPtr->val_ < 2 )
556 throw Exceptions::CoreOutOfRange( title_, args, 3, "The <count> must be at least 2." );
558 end = endPtr->val_;
559 step = stepPtr->val_;
560 begin = end - step * ( countPtr->val_ - 1 );
561 end -= 0.5 * step;
562 appendEnd = true;
564 else if( endPtr == NullPtr< ArgType >( ) )
566 if( stepPtr == NullPtr< ArgType >( ) )
568 throw Exceptions::CoreRequirement( "The <step> must be provided when constructing a range of floats when <end> is omitted.", title_, callLoc );
570 if( countPtr == NullPtr< CountType >( ) )
572 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of floats when <end> is omitted.", title_, callLoc );
574 if( countPtr->val_ < 2 )
576 throw Exceptions::CoreOutOfRange( title_, args, 3, "The <count> must be at least 2." );
578 begin = beginPtr->val_;
579 step = stepPtr->val_;
580 end = begin + step * ( countPtr->val_ - 0.5 );
582 else
584 // When we reach here, we know that at most one of <step> and <count> is provided.
585 if( stepPtr != NullPtr< ArgType >( ) )
587 begin = beginPtr->val_;
588 end = endPtr->val_;
589 step = stepPtr->val_;
591 else if( countPtr != NullPtr< CountType >( ) )
593 if( countPtr->val_ < 2 )
595 throw Exceptions::CoreOutOfRange( title_, args, 3, "The number of elements must be at least 2." );
597 begin = beginPtr->val_;
598 end = endPtr->val_;
599 step = ( end - begin ) / ( countPtr->val_ - 1 );
600 end -= 0.5 * step;
601 appendEnd = true;
603 else
605 begin = beginPtr->val_;
606 end = endPtr->val_;
610 std::list< double > tmp;
612 RefCountPtr< const Lang::SingleList > res = Lang::THE_CONS_NULL;
613 if( step > 0 )
615 for( double x = begin; x < end; x += step )
617 tmp.push_back( x );
620 else if( step < 0 )
622 for( double x = begin; x > end; x += step )
624 tmp.push_back( x );
627 else
629 throw Exceptions::CoreOutOfRange( title_, args, 2, "Step size must not be zero." );
631 if( appendEnd )
633 tmp.push_back( endPtr->val_ );
636 while( ! tmp.empty( ) )
638 res = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( Helpers::newValHandle( new Lang::Float( tmp.back( ) ) ),
639 res ) );
640 tmp.pop_back( );
643 Kernel::ContRef cont = evalState->cont_;
644 cont->takeValue( res,
645 evalState );
646 return;
648 catch( const NonLocalExit::NotThisType & ball )
650 // Never mind, see below
655 typedef const Lang::Length ArgType;
657 RefCountPtr< ArgType > beginPtr = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 0 ), true );
658 RefCountPtr< ArgType > endPtr = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( 1 ), true );
659 if( beginPtr == NullPtr< ArgType >( ) && endPtr == NullPtr< ArgType >( ) )
661 throw Exceptions::CoreRequirement( "At least one of the arguments <begin> and <end> must be provided.", title_, callLoc );
663 RefCountPtr< ArgType > stepPtr = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 2, callLoc, true );
664 RefCountPtr< CountType > countPtr = Helpers::down_cast_CoreArgument< CountType >( title_, args, 3, callLoc, true );
666 if( beginPtr != NullPtr< ArgType >( ) && endPtr != NullPtr< ArgType >( ) &&
667 stepPtr != NullPtr< ArgType >( ) && countPtr != NullPtr< CountType >( ) )
669 throw Exceptions::CoreRequirement( "At least one of the arguments must be omitted.", title_, callLoc );
672 double begin = 0;
673 double end = -1;
674 double step = 1;
675 bool appendEnd = false;
676 if( beginPtr == NullPtr< ArgType >( ) )
678 if( stepPtr == NullPtr< ArgType >( ) )
680 throw Exceptions::CoreRequirement( "The <step> must be provided when constructing a range of lengths when <begin> is omitted.", title_, callLoc );
682 if( countPtr == NullPtr< CountType >( ) )
684 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of lengths when <begin> is omitted.", title_, callLoc );
686 if( countPtr->val_ < 2 )
688 throw Exceptions::CoreOutOfRange( title_, args, 3, "The <count> must be at least 2." );
690 end = endPtr->getScalar( );
691 step = stepPtr->getScalar( );
692 begin = end - step * ( countPtr->val_ - 1 );
693 end -= 0.5 * step;
694 appendEnd = true;
696 else if( endPtr == NullPtr< ArgType >( ) )
698 if( stepPtr == NullPtr< ArgType >( ) )
700 throw Exceptions::CoreRequirement( "The <step> must be provided when constructing a range of lengths when <end> is omitted.", title_, callLoc );
702 if( countPtr == NullPtr< CountType >( ) )
704 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of lengths when <end> is omitted.", title_, callLoc );
706 if( countPtr->val_ < 2 )
708 throw Exceptions::CoreOutOfRange( title_, args, 3, "The <count> must be at least 2." );
710 begin = beginPtr->getScalar( );
711 step = stepPtr->getScalar( );
712 end = begin + step * ( countPtr->val_ - 0.5 );
714 else
716 if( stepPtr == NullPtr< ArgType >( ) && countPtr == NullPtr< CountType >( ) )
718 throw Exceptions::CoreRequirement( "Either of the <step> and <count> arguments must be provided when constructing a range of lengths from <begin> to <end>.", title_, callLoc );
720 // When we reach here, we know that exactly one of <step> and <count> is provided.
721 if( stepPtr != NullPtr< ArgType >( ) )
723 begin = beginPtr->getScalar( );
724 end = endPtr->getScalar( );
725 step = stepPtr->getScalar( );
727 else
729 begin = beginPtr->getScalar( );
730 end = endPtr->getScalar( );
731 // We know countPtr is not null here.
732 if( countPtr->val_ < 2 )
734 throw Exceptions::CoreOutOfRange( title_, args, 3, "The number of elements must be at least 2." );
736 step = ( end - begin ) / ( countPtr->val_ - 1 );
737 end -= 0.5 * step;
738 appendEnd = true;
743 std::list< double > tmp;
745 RefCountPtr< const Lang::SingleList > res = Lang::THE_CONS_NULL;
746 if( step > 0 )
748 for( double x = begin; x < end; x += step )
750 tmp.push_back( x );
753 else if( step < 0 )
755 for( double x = begin; x > end; x += step )
757 tmp.push_back( x );
760 else
762 throw Exceptions::CoreOutOfRange( title_, args, 2, "Step size must not be zero." );
764 if( appendEnd )
766 tmp.push_back( endPtr->getScalar( ) );
769 while( ! tmp.empty( ) )
771 res = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( Helpers::newValHandle( new Lang::Length( tmp.back( ) ) ),
772 res ) );
773 tmp.pop_back( );
776 Kernel::ContRef cont = evalState->cont_;
777 cont->takeValue( res,
778 evalState );
779 return;
781 catch( const NonLocalExit::NotThisType & ball )
783 // Never mind, see below
786 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::Integer::staticTypeName( ), Lang::Float::staticTypeName( ), Lang::Length::staticTypeName( ) ) );
790 class Core_affinetransform : public Lang::CoreFunction
792 public:
793 Core_affinetransform( const char * title ) : CoreFunction( title ) { }
794 virtual void
795 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
797 const size_t ARITY = 3;
798 CHECK_ARITY( args, ARITY, title_ );
800 typedef const Lang::FloatPair ArgType0;
801 typedef const Lang::FloatPair ArgType1;
802 typedef const Lang::Coords2D ArgType2;
804 RefCountPtr< ArgType0 > argx = Helpers::down_cast_CoreArgument< ArgType0 >( title_, args, 0, callLoc );
805 RefCountPtr< ArgType1 > argy = Helpers::down_cast_CoreArgument< ArgType1 >( title_, args, 1, callLoc );
806 RefCountPtr< ArgType2 > arg1 = Helpers::down_cast_CoreArgument< ArgType2 >( title_, args, 2, callLoc );
808 Kernel::ContRef cont = evalState->cont_;
809 cont->takeValue( Kernel::ValueRef( new Lang::Transform2D( argx->x_, argx->y_, argy->x_, argy->y_, arg1->x_.get( ), arg1->y_.get( ) ) ),
810 evalState );
814 class Core_affinetransform3D : public Lang::CoreFunction
816 public:
817 Core_affinetransform3D( const char * title ) : CoreFunction( title ) { }
818 virtual void
819 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
821 const size_t ARITY = 4;
822 CHECK_ARITY( args, ARITY, title_ );
824 typedef const Lang::FloatTriple ArgType0;
825 typedef const Lang::FloatTriple ArgType1;
826 typedef const Lang::FloatTriple ArgType2;
827 typedef const Lang::Coords3D ArgType3;
829 RefCountPtr< ArgType0 > argx = Helpers::down_cast_CoreArgument< ArgType0 >( title_, args, 0, callLoc );
830 RefCountPtr< ArgType1 > argy = Helpers::down_cast_CoreArgument< ArgType1 >( title_, args, 1, callLoc );
831 RefCountPtr< ArgType2 > argz = Helpers::down_cast_CoreArgument< ArgType2 >( title_, args, 2, callLoc );
832 RefCountPtr< ArgType3 > arg1 = Helpers::down_cast_CoreArgument< ArgType3 >( title_, args, 3, callLoc );
834 Kernel::ContRef cont = evalState->cont_;
835 cont->takeValue( Kernel::ValueRef( new Lang::Transform3D( argx->x_, argx->y_, argx->z_,
836 argy->x_, argy->y_, argy->z_,
837 argz->x_, argz->y_, argz->z_,
838 arg1->x_.get( ), arg1->y_.get( ), arg1->z_.get( ) ) ),
839 evalState );
843 class Core_shift : public Lang::CoreFunction
845 public:
846 Core_shift( const char * title ) : CoreFunction( title ) { }
847 virtual void
848 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
850 const size_t ARITY = 1;
851 CHECK_ARITY( args, ARITY, title_ );
853 Kernel::ContRef cont = evalState->cont_;
855 size_t i = 0;
858 typedef const Lang::Coords2D ArgType1;
859 RefCountPtr< ArgType1 > arg1 = Helpers::try_cast_CoreArgument< ArgType1 >( args.getValue( i ) );
860 cont->takeValue( Kernel::ValueRef( new Lang::Transform2D( 1, 0, 0, 1, arg1->x_.get( ), arg1->y_.get( ) ) ),
861 evalState );
862 return;
864 catch( const NonLocalExit::NotThisType & ball )
866 // Never mind, see below
871 typedef const Lang::Coords3D ArgType1;
872 RefCountPtr< ArgType1 > arg1 = Helpers::try_cast_CoreArgument< ArgType1 >( args.getValue( i ) );
873 cont->takeValue( Kernel::ValueRef( new Lang::Transform3D( 1, 0, 0, 0, 1, 0, 0, 0, 1, arg1->x_.get( ), arg1->y_.get( ), arg1->z_.get( ) ) ),
874 evalState );
875 return;
877 catch( const NonLocalExit::NotThisType & ball )
879 // Never mind, see below
882 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, i, Helpers::typeSetString( Lang::Coords2D::staticTypeName( ), Lang::Coords3D::staticTypeName( ) ) );
886 class Core_rotate : public Lang::CoreFunction
888 public:
889 Core_rotate( const char * title )
890 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
892 formals_->appendEvaluatedCoreFormal( "angle", Kernel::THE_SLOT_VARIABLE );
894 virtual void
895 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
897 args.applyDefaults( );
899 size_t i = 0;
901 typedef const Lang::Float ArgType1;
902 RefCountPtr< ArgType1 > arg1 = Helpers::down_cast_CoreArgument< ArgType1 >( title_, args, i, callLoc );
904 double c = cos( arg1->val_ );
905 double s = sin( arg1->val_ );
906 Kernel::ContRef cont = evalState->cont_;
907 cont->takeValue( Kernel::ValueRef( new Lang::Transform2D( c, s, -s, c, 0, 0 ) ),
908 evalState );
912 class Core_rotate3d : public Lang::CoreFunction
914 public:
915 Core_rotate3d( const char * title )
916 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
918 formals_->appendEvaluatedCoreFormal( "dir", Kernel::THE_SLOT_VARIABLE );
919 formals_->appendEvaluatedCoreFormal( "angle", Kernel::THE_SLOT_VARIABLE );
921 virtual void
922 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
924 args.applyDefaults( );
926 size_t i = 0;
928 typedef const Lang::FloatTriple ArgType1;
929 RefCountPtr< ArgType1 > dir = Helpers::down_cast_CoreArgument< ArgType1 >( title_, args, i, callLoc );
930 if( dir->x_ == 0 && dir->y_ == 0 && dir->z_ == 0 )
932 throw Exceptions::CoreOutOfRange( title_, args, i, "The rotation direction is degenerate, that is (0,0,0)." );
935 ++i;
937 typedef const Lang::Float ArgType2;
938 RefCountPtr< ArgType2 > angle = Helpers::down_cast_CoreArgument< ArgType2 >( title_, args, i, callLoc );
940 double r = sqrt( dir->x_ * dir->x_ + dir->y_ * dir->y_ + dir->z_ * dir->z_ );
941 double x = dir->x_ / r;
942 double y = dir->y_ / r;
943 double z = dir->z_ / r;
944 double x2 = x * x;
945 double y2 = y * y;
946 double z2 = z * z;
947 double c = cos( angle->val_ );
948 double s = sin( angle->val_ );
949 Kernel::ContRef cont = evalState->cont_;
950 cont->takeValue( Kernel::ValueRef( new Lang::Transform3D( x2+(y2+z2)*c, x*y*(1-c)+z*s, x*z*(1-c)-y*s,
951 x*y*(1-c)-z*s, y2+(x2+z2)*c, y*z*(1-c)+x*s,
952 x*z*(1-c)+y*s, y*z*(1-c)-x*s, z2+(x2+y2)*c,
953 0, 0, 0 ) ),
954 evalState );
958 class Core_scale : public Lang::CoreFunction
960 public:
961 Core_scale( const char * title )
962 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
964 Kernel::VariableHandle one( new Kernel::Variable( RefCountPtr< const Lang::Value >( new Lang::Float( 1 ) ) ) );
966 formals_->appendEvaluatedCoreFormal( "r", one );
967 formals_->appendEvaluatedCoreFormal( "x", one );
968 formals_->appendEvaluatedCoreFormal( "y", one );
970 virtual void
971 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
973 args.applyDefaults( );
975 typedef const Lang::Float ArgType;
976 RefCountPtr< ArgType > argr = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
977 RefCountPtr< ArgType > argx = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 1, callLoc );
978 RefCountPtr< ArgType > argy = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 2, callLoc );
980 Kernel::ContRef cont = evalState->cont_;
981 cont->takeValue( Kernel::ValueRef( new Lang::Transform2D( argr->val_ * argx->val_, 0,
982 0, argr->val_ * argy->val_,
983 0, 0 ) ),
984 evalState );
988 class Core_scale3d : public Lang::CoreFunction
990 public:
991 Core_scale3d( const char * title )
992 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
994 Kernel::VariableHandle one( new Kernel::Variable( RefCountPtr< const Lang::Value >( new Lang::Float( 1 ) ) ) );
996 formals_->appendEvaluatedCoreFormal( "r", one );
997 formals_->appendEvaluatedCoreFormal( "x", one );
998 formals_->appendEvaluatedCoreFormal( "y", one );
999 formals_->appendEvaluatedCoreFormal( "z", one );
1001 virtual void
1002 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1004 args.applyDefaults( );
1006 typedef const Lang::Float ArgType;
1007 RefCountPtr< ArgType > argr = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
1008 RefCountPtr< ArgType > argx = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 1, callLoc );
1009 RefCountPtr< ArgType > argy = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 2, callLoc );
1010 RefCountPtr< ArgType > argz = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 3, callLoc );
1012 Kernel::ContRef cont = evalState->cont_;
1013 cont->takeValue( Kernel::ValueRef( new Lang::Transform3D( argr->val_ * argx->val_, 0, 0,
1014 0, argr->val_ * argy->val_, 0,
1015 0, 0, argr->val_ * argz->val_,
1016 0, 0, 0 ) ),
1017 evalState );
1021 class Core_inverse : public Lang::CoreFunction
1023 public:
1024 Core_inverse( const char * title ) : CoreFunction( title ) { }
1025 virtual void
1026 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1028 const size_t ARITY = 1;
1029 CHECK_ARITY( args, ARITY, title_ );
1032 typedef const Lang::Transform2D ArgType;
1033 ArgType * tf = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1034 if( tf != 0 )
1036 double det = tf->xx_ * tf->yy_ - tf->xy_ * tf->yx_;
1037 if( fabs( det ) < Computation::SINGULAR_TRANSFORM_LIMIT )
1039 throw Exceptions::CoreOutOfRange( title_, args, 0, "Singular transforms cannot be inverted." );
1041 double idet = 1 / det;
1042 double ixx = idet * tf->yy_;
1043 double ixy = - idet * tf->xy_;
1044 double iyx = - idet * tf->yx_;
1045 double iyy = idet * tf->xx_;
1046 Kernel::ContRef cont = evalState->cont_;
1047 cont->takeValue( Kernel::ValueRef( new Lang::Transform2D( ixx, iyx,
1048 ixy, iyy,
1049 -( ixx * tf->xt_ + ixy * tf->yt_ ), -( iyx * tf->xt_ + iyy * tf->yt_ ) ) ),
1050 evalState );
1051 return;
1056 typedef const Lang::Transform3D ArgType;
1057 ArgType * tf = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1058 if( tf != 0 )
1060 double det =
1061 tf->xx_ * ( tf->yy_ * tf->zz_ - tf->yz_ * tf->zy_ )
1062 - tf->xy_ * ( tf->yx_ * tf->zz_ - tf->yz_ * tf->zx_ )
1063 + tf->xz_ * ( tf->yx_ * tf->zy_ - tf->yy_ * tf->zx_ );
1064 if( fabs( det ) < Computation::SINGULAR_TRANSFORM_LIMIT )
1066 throw Exceptions::CoreOutOfRange( title_, args, 0, "Singular transforms cannot be inverted." );
1068 double idet = 1 / det;
1069 double ixx = idet * ( tf->yy_ * tf->zz_ - tf->yz_ * tf->zy_ );
1070 double ixy = - idet * ( tf->xy_ * tf->zz_ - tf->xz_ * tf->zy_ );
1071 double ixz = idet * ( tf->xy_ * tf->yz_ - tf->xz_ * tf->yy_ );
1072 double iyx = - idet * ( tf->yx_ * tf->zz_ - tf->yz_ * tf->zx_ );
1073 double iyy = idet * ( tf->xx_ * tf->zz_ - tf->xz_ * tf->zx_ );
1074 double iyz = - idet * ( tf->xx_ * tf->yz_ - tf->xz_ * tf->yx_ );
1075 double izx = idet * ( tf->yx_ * tf->zy_ - tf->yy_ * tf->zx_ );
1076 double izy = - idet * ( tf->xx_ * tf->zy_ - tf->xy_ * tf->zx_ );
1077 double izz = idet * ( tf->xx_ * tf->yy_ - tf->xy_ * tf->yx_ );
1078 Kernel::ContRef cont = evalState->cont_;
1079 cont->takeValue( Kernel::ValueRef( new Lang::Transform3D( ixx, iyx, izx,
1080 ixy, iyy, izy,
1081 ixz, iyz, izz,
1082 -( ixx * tf->xt_ + ixy * tf->yt_ + ixz * tf->zt_ ),
1083 -( iyx * tf->xt_ + iyy * tf->yt_ + iyz * tf->zt_ ),
1084 -( izx * tf->xt_ + izy * tf->yt_ + izz * tf->zt_ ) ) ),
1085 evalState );
1086 return;
1090 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::Transform2D::staticTypeName( ), Lang::Transform3D::staticTypeName( ) ) );
1094 class Core_formxo : public Lang::CoreFunction
1096 public:
1097 Core_formxo( const char * title ) : CoreFunction( title ) { }
1098 virtual void
1099 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1101 const size_t ARITY = 1;
1102 CHECK_ARITY( args, ARITY, title_ );
1104 typedef const Lang::Drawable2D ArgType;
1105 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
1107 RefCountPtr< const Lang::ElementaryPath2D > theBBox = arg->bbox( Lang::Drawable2D::BOUNDING );
1108 Concrete::Coords2D llcorner( 0, 0 );
1109 Concrete::Coords2D urcorner( 0, 0 );
1110 if( ! theBBox->boundingRectangle( & llcorner, & urcorner ) )
1112 std::string strTitle( title_ );
1113 throw Exceptions::InternalError( strrefdup( strTitle + ": The object has no bounding box!" ) );
1117 RefCountPtr< SimplePDF::PDF_Stream_out > form;
1118 RefCountPtr< SimplePDF::PDF_Object > indirection = SimplePDF::indirect( form, & Kernel::theIndirectObjectCount );
1120 RefCountPtr< SimplePDF::PDF_Resources > resources;
1121 (*form)[ "Resources" ] = SimplePDF::indirect( resources, & Kernel::theIndirectObjectCount );
1123 (*form)[ "Subtype" ] = SimplePDF::newName( "Form" );
1124 (*form)[ "FormType" ] = SimplePDF::newInt( 1 );
1125 (*form)[ "BBox" ] = RefCountPtr< SimplePDF::PDF_Vector >( new SimplePDF::PDF_Vector( llcorner.x_.offtype< 1, 0 >( ), llcorner.y_.offtype< 1, 0 >( ),
1126 urcorner.x_.offtype< 1, 0 >( ), urcorner.y_.offtype< 1, 0 >( ) ) );
1128 /* There's a possibility of adding a transformation matrix entry in the dictionary here, but it is not used, not even
1129 * for transformed drawables.
1131 // (*markForm)[ "Matrix" ] = RefCountPtr<PDF_Object>( new PDF_Vector( 1, 0, 0, 1, -30, -30 ) );
1133 Kernel::PageContentStates pdfState( resources );
1134 arg->shipout( form->data, & pdfState, Lang::Transform2D( 1, 0, 0, 1, 0, 0 ) );
1137 Lang::XObject * res = new Lang::XObject( indirection,
1138 theBBox );
1139 res->setDebugStr( "user form" );
1140 Kernel::ContRef cont = evalState->cont_;
1141 cont->takeValue( Kernel::ValueRef( res ),
1142 evalState );
1146 class Core_transparencygroup : public Lang::CoreFunction
1148 public:
1149 Core_transparencygroup( const char * title )
1150 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1152 formals_->appendEvaluatedCoreFormal( "content", Kernel::THE_SLOT_VARIABLE );
1153 formals_->appendEvaluatedCoreFormal( "isolated", Kernel::THE_FALSE_VARIABLE );
1154 formals_->appendEvaluatedCoreFormal( "knockout", Kernel::THE_FALSE_VARIABLE );
1156 virtual void
1157 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1159 args.applyDefaults( );
1161 typedef const Lang::Group2D ArgType0;
1162 typedef const Lang::Boolean ArgType1;
1163 typedef const Lang::Boolean ArgType2;
1164 RefCountPtr< ArgType0 > content = Helpers::down_cast_CoreArgument< ArgType0 >( title_, args, 0, callLoc );
1165 RefCountPtr< ArgType1 > isolated = Helpers::down_cast_CoreArgument< ArgType1 >( title_, args, 1, callLoc );
1166 RefCountPtr< ArgType2 > knockout = Helpers::down_cast_CoreArgument< ArgType2 >( title_, args, 2, callLoc );
1168 RefCountPtr< const Lang::ColorSpace > blendSpace = evalState->dyn_->getBlendSpace( );
1170 Kernel::ContRef cont = evalState->cont_;
1171 cont->takeValue( Helpers::newTransparencyGroup( content, isolated->val_, knockout->val_, blendSpace ),
1172 evalState );
1176 class Core_vector : public Lang::CoreFunction
1178 public:
1179 Core_vector( const char * title ) : CoreFunction( title ) { }
1180 virtual void
1181 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1183 std::vector< RefCountPtr< const Lang::Value > > * res = new std::vector< RefCountPtr< const Lang::Value > >;
1184 res->reserve( args.size( ) );
1186 for( size_t i = 0; i != args.size( ); ++i )
1188 res->push_back( args.getValue( i ) );
1191 Kernel::ContRef cont = evalState->cont_;
1192 cont->takeValue( Kernel::ValueRef( new Lang::VectorFunction( res ) ),
1193 evalState );
1197 class Core_interpolate : public Lang::CoreFunction
1199 public:
1200 Core_interpolate( const char * title )
1201 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1203 formals_->appendEvaluatedCoreFormal( "function", Kernel::THE_SLOT_VARIABLE );
1204 formals_->appendEvaluatedCoreFormal( "domain", Kernel::THE_SLOT_VARIABLE );
1205 formals_->appendEvaluatedCoreFormal( "size", Kernel::THE_SLOT_VARIABLE );
1206 formals_->appendEvaluatedCoreFormal( "range", Kernel::THE_SLOT_VARIABLE );
1207 formals_->appendEvaluatedCoreFormal( "encode", Kernel::THE_VOID_VARIABLE );
1208 formals_->appendEvaluatedCoreFormal( "decode", Kernel::THE_VOID_VARIABLE );
1210 virtual void
1211 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1213 args.applyDefaults( );
1215 throw Exceptions::NotImplemented( "Core_interpolate::call" );
1219 class Core_importPDFpages : public Lang::CoreFunction
1221 public:
1222 Core_importPDFpages( const char * title ) : CoreFunction( title ) { }
1223 virtual void
1224 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1226 const size_t ARITY = 1;
1227 CHECK_ARITY( args, ARITY, title_ );
1229 typedef const Lang::String ArgType;
1230 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
1232 RefCountPtr< std::ifstream > iFile( new std::ifstream( arg->val_.getPtr( ) ) );
1233 if( ! iFile->good( ) )
1235 std::ostringstream msg;
1236 msg << "Failed to open file for input: " << arg->val_.getPtr( ) ;
1237 throw Exceptions::CoreOutOfRange( title_, args, 0, strrefdup( msg ) );
1239 RefCountPtr< SimplePDF::PDF_in > pdfi( new SimplePDF::PDF_in( iFile ) );
1241 RefCountPtr< const std::vector< RefCountPtr< const Lang::XObject > > > typedRes = RefCountPtr< const std::vector< RefCountPtr< const Lang::XObject > > >( NullPtr< std::vector< RefCountPtr< const Lang::XObject > > >( ) );
1244 typedRes = Kernel::thePDFImporter.addPagesAsXObjects( pdfi );
1246 catch( const char * ball )
1248 throw Exceptions::InternalError( strrefdup( ( std::string( "An error occurred while importing " ) + arg->val_.getPtr( ) + ": " + ball ).c_str( ) ) );
1251 std::vector< RefCountPtr< const Lang::Value > > * untypedRes = new std::vector< RefCountPtr< const Lang::Value > >;
1252 untypedRes->reserve( typedRes->size( ) );
1253 typedef typeof *typedRes ListType;
1254 for( ListType::const_iterator i = typedRes->begin( ); i != typedRes->end( ); ++i )
1256 untypedRes->push_back( *i );
1259 Kernel::ContRef cont = evalState->cont_;
1260 cont->takeValue( Kernel::ValueRef( new Lang::VectorFunction( untypedRes ) ),
1261 evalState );
1265 namespace Implementation
1267 double
1268 svg_path_strtod( const char ** src )
1270 const char * start = *src;
1271 char * endp;
1272 double res = strtod( start, & endp );
1273 *src = endp;
1274 if( **src != ' ' )
1276 for( ; *start == ' '; ++start )
1278 throw std::string( start, strchr( start, ' ' ) - start );
1280 return res;
1283 class Core_svg_path : public Lang::CoreFunction
1285 public:
1286 Core_svg_path( const char * title )
1287 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1289 formals_->appendEvaluatedCoreFormal( "d", Kernel::THE_SLOT_VARIABLE );
1290 formals_->appendEvaluatedCoreFormal( "xunit", Helpers::newValHandle( new Lang::Length( Concrete::Length( 1 ) ) ) );
1291 formals_->appendEvaluatedCoreFormal( "yunit", Helpers::newValHandle( new Lang::Length( Concrete::Length( 1 ) ) ) );
1292 formals_->appendEvaluatedCoreFormal( "multi", Kernel::THE_VOID_VARIABLE );
1293 formals_->appendEvaluatedCoreFormal( "singletons", Kernel::THE_TRUE_VARIABLE );
1295 virtual void
1296 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1298 args.applyDefaults( );
1300 size_t argsi = 0;
1301 typedef const Lang::String StrType;
1302 RefCountPtr< StrType > arg = Helpers::down_cast_CoreArgument< StrType >( title_, args, argsi, callLoc );
1304 typedef const Lang::Length ScaleType;
1305 ++argsi;
1306 Concrete::Length dx = Helpers::down_cast_CoreArgument< ScaleType >( title_, args, argsi, callLoc )->get( );
1307 ++argsi;
1308 Concrete::Length dy = Helpers::down_cast_CoreArgument< ScaleType >( title_, args, argsi, callLoc )->get( );
1310 typedef const Lang::Boolean FlagType;
1311 ++argsi;
1312 RefCountPtr< FlagType > multi = Helpers::down_cast_CoreArgument< FlagType >( title_, args, argsi, callLoc, true );
1313 ++argsi;
1314 bool singletons = Helpers::down_cast_CoreArgument< FlagType >( title_, args, argsi, callLoc )->val_;
1316 RefCountPtr< char > buf = RefCountPtr< char >( new char[ 2 * strlen( arg->val_.getPtr( ) + 1 ) ] );
1318 /* Get rid of any whitespace that isn't a plain space, and make sure every number is terminated by whitespace.
1320 char * dst = buf.getPtr( );
1321 for( const char * src = arg->val_.getPtr( ); *src != '\0'; ++src, ++dst )
1323 switch( *src )
1325 case '\t':
1326 case '\n':
1327 case ',':
1328 *dst = ' ';
1329 continue;
1331 if( ( 'A' <= *src && *src <= 'Z' ) || ( 'a' <= *src && *src <= 'z' ) )
1333 /* Insert whitespace before command to ensure command is not immediately following number.
1335 *dst = ' ';
1336 ++dst;
1338 *dst = *src;
1340 *dst = ' ';
1341 ++dst;
1342 *dst = '\0';
1345 RefCountPtr< Lang::MultiPath2D > multiPath = RefCountPtr< Lang::MultiPath2D >( new Lang::MultiPath2D );
1346 RefCountPtr< Lang::ElementaryPath2D > elemPath = RefCountPtr< Lang::ElementaryPath2D >( NullPtr< Lang::ElementaryPath2D >( ) );
1350 char cmd = '\0';
1351 Concrete::PathPoint2D originPathPoint( new Concrete::Coords2D( 0, 0 ) );
1352 Concrete::PathPoint2D * first = & originPathPoint;
1353 Concrete::PathPoint2D * last = & originPathPoint;
1354 const char * srcEnd = buf.getPtr( ) + strlen( buf.getPtr( ) );
1355 for( const char * src = buf.getPtr( ); src < srcEnd; ++src )
1357 for( ; *src == ' '; ++src )
1359 if( *src == '\0' )
1361 break;
1363 switch( *src )
1365 case 'M':
1366 case 'm':
1367 case 'Z':
1368 case 'z':
1369 case 'L':
1370 case 'l':
1371 case 'H':
1372 case 'h':
1373 case 'V':
1374 case 'v':
1375 case 'C':
1376 case 'c':
1377 case 'S':
1378 case 's':
1380 cmd = *src;
1381 ++src;
1382 break;
1384 case 'Q':
1385 case 'q':
1386 case 'T':
1387 case 't':
1388 case 'A':
1389 case 'a':
1391 throw Exceptions::CoreOutOfRange( title_, args, 0, strrefdup( std::string( "SVG path command not compatible with cubic splines: " ) + *src ) );
1394 switch( cmd )
1396 case 'M':
1398 if( elemPath != NullPtr< Lang::ElementaryPath2D >( ) && ( singletons || elemPath->duration( ) >= 1 ) )
1400 multiPath->push_back( elemPath );
1402 Concrete::Length x = dx * Implementation::svg_path_strtod( & src );
1403 Concrete::Length y = - dy * Implementation::svg_path_strtod( & src );
1404 first = new Concrete::PathPoint2D( new Concrete::Coords2D( x, y ) );
1405 last = first;
1406 elemPath = RefCountPtr< Lang::ElementaryPath2D >( new Lang::ElementaryPath2D );
1407 elemPath->push_back( last );
1408 cmd = 'L';
1409 break;
1411 case 'm':
1413 if( elemPath != NullPtr< Lang::ElementaryPath2D >( ) && ( singletons || elemPath->duration( ) >= 1 ) )
1415 multiPath->push_back( elemPath );
1417 Concrete::Length x = last->mid_->x_ + dx * Implementation::svg_path_strtod( & src );
1418 Concrete::Length y = last->mid_->y_ - dy * Implementation::svg_path_strtod( & src );
1419 first = new Concrete::PathPoint2D( new Concrete::Coords2D( x, y ) );
1420 last = first;
1421 elemPath = RefCountPtr< Lang::ElementaryPath2D >( new Lang::ElementaryPath2D );
1422 elemPath->push_back( last );
1423 cmd = 'l';
1424 break;
1426 case 'Z':
1428 elemPath->close( );
1429 last = first;
1430 break;
1432 case 'z':
1434 elemPath->close( );
1435 last = first;
1436 break;
1438 case 'L':
1440 Concrete::Length x = dx * Implementation::svg_path_strtod( & src );
1441 Concrete::Length y = - dy * Implementation::svg_path_strtod( & src );
1442 last = new Concrete::PathPoint2D( new Concrete::Coords2D( x, y ) );
1443 elemPath->push_back( last );
1444 break;
1446 case 'l':
1448 Concrete::Length x = last->mid_->x_ + dx * Implementation::svg_path_strtod( & src );
1449 Concrete::Length y = last->mid_->y_ - dy * Implementation::svg_path_strtod( & src );
1450 last = new Concrete::PathPoint2D( new Concrete::Coords2D( x, y ) );
1451 elemPath->push_back( last );
1452 break;
1454 case 'H':
1456 Concrete::Length x = dx * Implementation::svg_path_strtod( & src );
1457 last = new Concrete::PathPoint2D( new Concrete::Coords2D( x, last->mid_->y_ ) );
1458 elemPath->push_back( last );
1459 break;
1461 case 'h':
1463 Concrete::Length x = last->mid_->x_ + dx * Implementation::svg_path_strtod( & src );
1464 last = new Concrete::PathPoint2D( new Concrete::Coords2D( x, last->mid_->y_ ) );
1465 elemPath->push_back( last );
1466 break;
1468 case 'V':
1470 Concrete::Length y = - dy * Implementation::svg_path_strtod( & src );
1471 last = new Concrete::PathPoint2D( new Concrete::Coords2D( last->mid_->x_, y ) );
1472 elemPath->push_back( last );
1473 break;
1475 case 'v':
1477 Concrete::Length y = last->mid_->y_ - dy * Implementation::svg_path_strtod( & src );
1478 last = new Concrete::PathPoint2D( new Concrete::Coords2D( last->mid_->x_, y ) );
1479 elemPath->push_back( last );
1480 break;
1482 case 'C':
1484 Concrete::Length x1 = dx * Implementation::svg_path_strtod( & src );
1485 Concrete::Length y1 = - dy * Implementation::svg_path_strtod( & src );
1486 Concrete::Length x2 = dx * Implementation::svg_path_strtod( & src );
1487 Concrete::Length y2 = - dy * Implementation::svg_path_strtod( & src );
1488 Concrete::Length x3 = dx * Implementation::svg_path_strtod( & src );
1489 Concrete::Length y3 = - dy * Implementation::svg_path_strtod( & src );
1490 last->front_ = new Concrete::Coords2D( x1, y1 );
1491 last = new Concrete::PathPoint2D( new Concrete::Coords2D( x3, y3 ) );
1492 last->rear_ = new Concrete::Coords2D( x2, y2 );
1493 elemPath->push_back( last );
1494 break;
1496 case 'c':
1498 Concrete::Length x1 = last->mid_->x_ + dx * Implementation::svg_path_strtod( & src );
1499 Concrete::Length y1 = last->mid_->y_ - dy * Implementation::svg_path_strtod( & src );
1500 Concrete::Length x2 = last->mid_->x_ + dx * Implementation::svg_path_strtod( & src );
1501 Concrete::Length y2 = last->mid_->y_ - dy * Implementation::svg_path_strtod( & src );
1502 Concrete::Length x3 = last->mid_->x_ + dx * Implementation::svg_path_strtod( & src );
1503 Concrete::Length y3 = last->mid_->y_ - dy * Implementation::svg_path_strtod( & src );
1504 last->front_ = new Concrete::Coords2D( x1, y1 );
1505 last = new Concrete::PathPoint2D( new Concrete::Coords2D( x3, y3 ) );
1506 last->rear_ = new Concrete::Coords2D( x2, y2 );
1507 elemPath->push_back( last );
1508 break;
1510 case 'S':
1512 Concrete::Length x2 = dx * Implementation::svg_path_strtod( & src );
1513 Concrete::Length y2 = - dy * Implementation::svg_path_strtod( & src );
1514 Concrete::Length x3 = dx * Implementation::svg_path_strtod( & src );
1515 Concrete::Length y3 = - dy * Implementation::svg_path_strtod( & src );
1516 last->front_ = new Concrete::Coords2D( 2 * *(last->mid_) - *(last->rear_) );
1517 last = new Concrete::PathPoint2D( new Concrete::Coords2D( x3, y3 ) );
1518 last->rear_ = new Concrete::Coords2D( x2, y2 );
1519 elemPath->push_back( last );
1520 break;
1522 case 's':
1524 Concrete::Length x2 = last->mid_->x_ + dx * Implementation::svg_path_strtod( & src );
1525 Concrete::Length y2 = last->mid_->y_ - dy * Implementation::svg_path_strtod( & src );
1526 Concrete::Length x3 = last->mid_->x_ + dx * Implementation::svg_path_strtod( & src );
1527 Concrete::Length y3 = last->mid_->y_ - dy * Implementation::svg_path_strtod( & src );
1528 last->front_ = new Concrete::Coords2D( 2 * *(last->mid_) - *(last->rear_) );
1529 last = new Concrete::PathPoint2D( new Concrete::Coords2D( x3, y3 ) );
1530 last->rear_ = new Concrete::Coords2D( x2, y2 );
1531 elemPath->push_back( last );
1532 break;
1534 case '\0':
1535 throw Exceptions::CoreOutOfRange( title_, args, 0, "Malformed SVG path string (failed to initialize command character)." );
1536 default:
1538 throw Exceptions::InternalError( "While reading SVG path string: Command character out of range." );
1543 catch( const std::string & badNumber )
1545 throw Exceptions::CoreOutOfRange( title_, args, 0, strrefdup( std::string( "Ill-formed number: " ) + badNumber ) );
1548 if( elemPath != NullPtr< Lang::ElementaryPath2D >( ) && ( singletons || elemPath->duration( ) >= 1 ) )
1550 multiPath->push_back( RefCountPtr< const Lang::Path2D >( elemPath ) );
1553 if( multiPath->size( ) == 0 )
1555 throw Exceptions::CoreOutOfRange( title_, args, 0, "No path was produced." );
1557 if( multiPath->size( ) == 1 )
1559 Kernel::ContRef cont = evalState->cont_;
1560 if( multi != NullPtr< FlagType >( ) && multi->val_ )
1562 cont->takeValue( Kernel::ValueRef( multiPath ),
1563 evalState );
1565 else
1567 cont->takeValue( Kernel::ValueRef( multiPath->front( ) ),
1568 evalState );
1571 else
1573 if( multi != NullPtr< FlagType >( ) && ! multi->val_ )
1575 throw Exceptions::CoreOutOfRange( title_, args, 0, "More than one sub-path conflicts with false for <multi>." );
1577 Kernel::ContRef cont = evalState->cont_;
1578 cont->takeValue( Kernel::ValueRef( multiPath ),
1579 evalState );
1584 class Core_sprintf : public Lang::CoreFunction
1586 public:
1587 Core_sprintf( const char * title ) : CoreFunction( title ) { }
1588 virtual void
1589 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1591 if( args.empty( ) )
1593 throw Exceptions::CoreArityMismatch( title_, 1, args.size( ) );
1595 typedef typeof args ArgListType;
1596 size_t i = 0;
1597 typedef const Lang::String Arg1Type;
1598 RefCountPtr< Arg1Type > arg1 = Helpers::down_cast_CoreArgument< Arg1Type >( title_, args, i, callLoc );
1600 /* snprintf( 0, 0, ... ) does not seem to work properly on some systems.
1601 * Therefore, I resort to the use of a dummy string, and "n = 1".
1603 char * res = 0;
1604 int status;
1605 char dummy[1];
1606 switch( args.size( ) )
1608 case 1:
1610 size_t sz = snprintf( dummy, 1, arg1->val_.getPtr( ), 0 ); /* The final 0 is just a dummy argument that makes the compiler relax. */
1611 res = new char[ sz + 1 ];
1612 status = sprintf( res, arg1->val_.getPtr( ), 0 ); /* The final 0 is just a dummy argument that makes the compiler relax. */
1614 break;
1615 case 2:
1617 ++i;
1619 typedef const Lang::String Arg2Type;
1620 Arg2Type * arg2 = dynamic_cast< Arg2Type * >( args.getValue( i ).getPtr( ) );
1621 if( arg2 != 0 )
1623 size_t sz = snprintf( dummy, 1, arg1->val_.getPtr( ), arg2->val_.getPtr( ) );
1624 res = new char[ sz + 1 ];
1625 status = sprintf( res, arg1->val_.getPtr( ), arg2->val_.getPtr( ) );
1626 break;
1630 typedef const Lang::Float Arg2Type;
1631 Arg2Type * arg2 = dynamic_cast< Arg2Type * >( args.getValue( i ).getPtr( ) );
1632 if( arg2 != 0 )
1634 size_t sz = snprintf( dummy, 1, arg1->val_.getPtr( ), arg2->val_ );
1635 res = new char[ sz + 1 ];
1636 status = sprintf( res, arg1->val_.getPtr( ), arg2->val_ );
1637 break;
1641 typedef const Lang::Integer Arg2Type;
1642 Arg2Type * arg2 = dynamic_cast< Arg2Type * >( args.getValue( i ).getPtr( ) );
1643 if( arg2 != 0 )
1645 size_t sz = snprintf( dummy, 1, arg1->val_.getPtr( ), arg2->val_ );
1646 res = new char[ sz + 1 ];
1647 status = sprintf( res, arg1->val_.getPtr( ), arg2->val_ );
1648 break;
1652 typedef const Lang::ChronologicalTime Arg2Type;
1653 Arg2Type * arg2 = dynamic_cast< Arg2Type * >( args.getValue( i ).getPtr( ) );
1654 if( arg2 != 0 )
1656 const char * fmt = arg1->val_.getPtr( );
1657 const struct tm * tmp = arg2->temporary_localtime( );
1658 size_t sz = strlen( fmt ) * 2;
1659 res = new char[ sz ];
1660 while( strftime( res, sz, fmt, tmp ) == 0 )
1662 delete res;
1663 sz *= 2;
1664 res = new char[ sz ];
1666 status = 0; // Here, I'd like to check some error condition instead...
1667 break;
1670 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, i, Interaction::SEVERAL_TYPES );
1672 break;
1673 default:
1674 throw Exceptions::CoreOutOfRange( title_, args, 0, "The number of arguments is out of the implemented range." );
1677 if( res == 0 )
1679 throw Exceptions::InternalError( "Failed to assign to res in sprintf." );
1682 if( status < 0 )
1684 std::ostringstream oss;
1685 oss << "Call to library routine returned negative value indicating an error: " << status << ".";
1686 throw Exceptions::CoreOutOfRange( title_, args, 0, strrefdup( oss ) );
1689 Kernel::ContRef cont = evalState->cont_;
1690 cont->takeValue( Kernel::ValueRef( new Lang::String( res, false ) ),
1691 evalState );
1695 class Core_strftime : public Lang::CoreFunction
1697 public:
1698 Core_strftime( const char * title ) : CoreFunction( title ) { }
1699 virtual void
1700 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1702 const size_t ARITY = 0;
1703 CHECK_ARITY( args, ARITY, title_ );
1705 time_t t;
1706 tm * timeInfo;
1707 t = time( 0 );
1708 timeInfo = localtime( & t );
1709 std::ostringstream res;
1710 res << timeInfo->tm_hour << ":" << timeInfo->tm_min << ":" << timeInfo->tm_sec ;
1712 Kernel::ContRef cont = evalState->cont_;
1713 cont->takeValue( Kernel::ValueRef( new Lang::String( strrefdup( res ) ) ),
1714 evalState );
1718 class Core_ambient_light : public Lang::CoreFunction
1720 public:
1721 Core_ambient_light( const char * title )
1722 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1724 formals_->appendEvaluatedCoreFormal( "color", Kernel::THE_SLOT_VARIABLE );
1726 virtual void
1727 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1729 args.applyDefaults( );
1732 typedef const Lang::Gray ArgType;
1733 ArgType * col = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1734 if( col != 0 )
1736 Kernel::ContRef cont = evalState->cont_;
1737 cont->takeValue( Kernel::ValueRef( new Lang::AmbientLightGray( col->components( ) ) ),
1738 evalState );
1739 return;
1744 typedef const Lang::RGB ArgType;
1745 ArgType * col = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1746 if( col != 0 )
1748 Kernel::ContRef cont = evalState->cont_;
1749 cont->takeValue( Kernel::ValueRef( new Lang::AmbientLightRGB( col->components( ) ) ),
1750 evalState );
1751 return;
1755 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::Gray::staticTypeName( ), Lang::RGB::staticTypeName( ) ) );
1759 class Core_specular_light : public Lang::CoreFunction
1761 public:
1762 Core_specular_light( const char * title )
1763 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1765 formals_->appendEvaluatedCoreFormal( "color", Kernel::THE_SLOT_VARIABLE );
1766 formals_->appendEvaluatedCoreFormal( "radius", Helpers::newValHandle( new Lang::Length( HUGE_VAL ) ) );
1767 formals_->appendEvaluatedCoreFormal( "shadows", Kernel::THE_FALSE_VARIABLE );
1769 virtual void
1770 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1772 args.applyDefaults( );
1774 typedef const Lang::Length RadiusType;
1775 RefCountPtr< RadiusType > radius = Helpers::down_cast_CoreArgument< RadiusType >( title_, args, 1, callLoc );
1776 typedef const Lang::Boolean ShadowsType;
1777 RefCountPtr< ShadowsType > shadows = Helpers::down_cast_CoreArgument< ShadowsType >( title_, args, 2, callLoc );
1780 typedef const Lang::Gray ArgType;
1781 ArgType * col = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1782 if( col != 0 )
1784 Kernel::ContRef cont = evalState->cont_;
1785 cont->takeValue( Kernel::ValueRef( new Lang::SpecularLightGray( Concrete::Coords3D( 0, 0, 0 ),
1786 col->components( ),
1787 radius->get( ),
1788 shadows->val_ ) ),
1789 evalState );
1790 return;
1795 typedef const Lang::RGB ArgType;
1796 ArgType * col = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1797 if( col != 0 )
1799 Kernel::ContRef cont = evalState->cont_;
1800 cont->takeValue( Kernel::ValueRef( new Lang::SpecularLightRGB( Concrete::Coords3D( 0, 0, 0 ),
1801 col->components( ),
1802 radius->get( ),
1803 shadows->val_ ) ),
1804 evalState );
1805 return;
1809 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::Gray::staticTypeName( ), Lang::RGB::staticTypeName( ) ) );
1813 class Core_distant_light : public Lang::CoreFunction
1815 public:
1816 Core_distant_light( const char * title )
1817 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1819 formals_->appendEvaluatedCoreFormal( "color", Kernel::THE_SLOT_VARIABLE );
1820 formals_->appendEvaluatedCoreFormal( "shadows", Kernel::THE_FALSE_VARIABLE );
1822 virtual void
1823 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1825 args.applyDefaults( );
1827 typedef const Lang::Boolean ShadowsType;
1828 RefCountPtr< ShadowsType > shadows = Helpers::down_cast_CoreArgument< ShadowsType >( title_, args, 1, callLoc );
1831 typedef const Lang::Gray ArgType;
1832 ArgType * col = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1833 if( col != 0 )
1835 Kernel::ContRef cont = evalState->cont_;
1836 cont->takeValue( Kernel::ValueRef( new Lang::DistantLightGray( Concrete::UnitFloatTriple( 0., 0., -1. ),
1837 col->components( ),
1838 shadows->val_ ) ),
1839 evalState );
1840 return;
1845 typedef const Lang::RGB ArgType;
1846 ArgType * col = dynamic_cast< ArgType * >( args.getValue( 0 ).getPtr( ) );
1847 if( col != 0 )
1849 Kernel::ContRef cont = evalState->cont_;
1850 cont->takeValue( Kernel::ValueRef( new Lang::DistantLightRGB( Concrete::UnitFloatTriple( 0., 0., -1. ),
1851 col->components( ),
1852 shadows->val_ ) ),
1853 evalState );
1854 return;
1858 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, 0, Helpers::typeSetString( Lang::Gray::staticTypeName( ), Lang::RGB::staticTypeName( ) ) );
1862 class Core_textrenderingmode : public Lang::CoreFunction
1864 public:
1865 Core_textrenderingmode( const char * title )
1866 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
1868 formals_->appendEvaluatedCoreFormal( "fill", Kernel::THE_FALSE_VARIABLE );
1869 formals_->appendEvaluatedCoreFormal( "stroke", Kernel::THE_FALSE_VARIABLE );
1871 virtual void
1872 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1874 args.applyDefaults( );
1876 typedef const Lang::Boolean FlagType;
1877 RefCountPtr< FlagType > fill = Helpers::down_cast_CoreArgument< FlagType >( title_, args, 0, callLoc );
1878 RefCountPtr< FlagType > stroke = Helpers::down_cast_CoreArgument< FlagType >( title_, args, 1, callLoc );
1880 Kernel::ContRef cont = evalState->cont_;
1881 cont->takeValue( Kernel::ValueRef( new Lang::TextRenderingMode( fill->val_, stroke->val_, false ) ),
1882 evalState );
1886 class Core_manualkern : public Lang::CoreFunction
1888 public:
1889 Core_manualkern( const char * title ) : CoreFunction( title ) { }
1890 virtual void
1891 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1893 // Note that res is _not_ yet const. We use a RefCountPtr to take care of memory deallocation in case some argument has the wrong type and
1894 // the result is not used.
1895 RefCountPtr< Lang::KernedText > res( new Lang::KernedText( evalState->dyn_->getTextState( ), evalState->dyn_->getGraphicsState( ) ) );
1897 for( size_t i = 0; i != args.size( ); ++i )
1901 typedef const Lang::String ArgType;
1902 res->pushString( Helpers::try_cast_CoreArgument< ArgType >( args.getValue( i ) ) );
1903 continue;
1905 catch( const NonLocalExit::NotThisType & ball )
1907 // Never mind, see below
1912 typedef const Lang::Float ArgType;
1913 res->pushKerning( Helpers::try_cast_CoreArgument< ArgType >( args.getValue( i ) )->val_ );
1914 continue;
1916 catch( const NonLocalExit::NotThisType & ball )
1918 // Never mind, see below
1923 typedef const Lang::KernedText ArgType;
1924 Helpers::try_cast_CoreArgument< ArgType >( args.getValue( i ) )->push( res.getPtr( ) );
1925 continue;
1927 catch( const NonLocalExit::NotThisType & ball )
1929 // Never mind, see below
1932 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, i, Helpers::typeSetString( Lang::String::staticTypeName( ), Lang::Float::staticTypeName( ), Lang::KernedText::staticTypeName( ) ) );
1935 Kernel::ContRef cont = evalState->cont_;
1936 cont->takeValue( res,
1937 evalState );
1941 class Core_automatickern : public Lang::CoreFunction
1943 public:
1944 Core_automatickern( const char * title ) : CoreFunction( title ) { }
1945 virtual void
1946 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1948 iconv_t converter = Helpers::requireUTF8ToMacRomanConverter( );
1949 iconv_t backconverter = Helpers::requireMacRomanToUTF8Converter( );
1951 RefCountPtr< const FontMetrics::BaseFont > metrics = evalState->dyn_->getTextState( )->font_->metrics( );
1952 if( metrics->horizontalMetrics_ == NullPtr< FontMetrics::WritingDirectionMetrics >( ) )
1954 throw Exceptions::FontMetricsError( evalState->dyn_->getTextState( )->font_->fontName( ), strrefdup( "No horizontal metrics defined." ) );
1957 // Note that res is _not_ yet const. We use a RefCountPtr to take care of memory deallocation in case some argument has the wrong type and
1958 // the result is not used.
1959 RefCountPtr< Lang::KernedText > res( new Lang::KernedText( evalState->dyn_->getTextState( ), evalState->dyn_->getGraphicsState( ) ) );
1961 std::ostringstream pendingChars;
1962 unsigned char prevChar = 0;
1963 double pendingKerning = 0;
1965 size_t backbufSize = 5;
1966 char * backbuf = new char[ backbufSize ];
1967 DeleteOnExit< char > bufDeleter( backbuf );
1969 for( size_t i = 0; i != args.size( ); ++i )
1973 typedef const Lang::String ArgType;
1974 RefCountPtr< ArgType > str = Helpers::try_cast_CoreArgument< ArgType >( args.getValue( i ) );
1976 const char * inbuf = str->val_.getPtr( );
1978 size_t bufSize = strlen( inbuf ) + 1;
1979 char * buf = new char[ bufSize ];
1980 DeleteOnExit< char > bufDeleter( buf );
1982 char * outbuf = buf;
1983 size_t inbytesleft = bufSize - 1;
1984 size_t outbytesleft = bufSize - 1;
1985 // The ICONV_CAST macro is defined in config.h.
1986 size_t count = iconv( converter,
1987 ICONV_CAST( & inbuf ), & inbytesleft,
1988 & outbuf, & outbytesleft );
1989 if( count == (size_t)(-1) )
1991 if( errno == EILSEQ )
1993 throw Exceptions::MiscellaneousRequirement( "It is suspected that one of the UFT-8 characters used in showed text has no MacRoman representation." );
1995 else if( errno == EINVAL )
1997 throw Exceptions::MiscellaneousRequirement( "It is suspected that showed text ended with an incomplete multibyte character." );
1999 else if( errno == E2BIG )
2001 throw Exceptions::InternalError( "The buffer allocated for UTF-8 to MacRoman conversion was too small." );
2003 else
2005 std::ostringstream msg;
2006 msg << "iconv failed with an unrecognized error code: " << errno ;
2007 throw Exceptions::InternalError( strrefdup( msg ) );
2010 *outbuf = '\0';
2011 for( const char * src = buf; *src != '\0'; ++src )
2013 unsigned char currentChar = *reinterpret_cast< const unsigned char * >( src );
2014 double currentKerning = pendingKerning - metrics->getHorizontalKernPairXByCode( prevChar, currentChar );
2015 prevChar = currentChar;
2016 pendingKerning = 0;
2017 if( currentKerning != 0 )
2019 if( ! pendingChars.str( ).empty( ) )
2021 res->pushString( RefCountPtr< const Lang::String >( new Lang::String( strrefdup( pendingChars ) ) ) );
2022 pendingChars.str( "" );
2024 res->pushKerning( currentKerning );
2027 // Copy the current (multibyte) character to the character queue
2029 const char * inbuf = src;
2030 char * outbuf = backbuf;
2031 size_t inbytesleft = 1;
2032 size_t outbytesleft = backbufSize;
2033 // The ICONV_CAST macro is defined in config.h.
2034 size_t count = iconv( backconverter,
2035 ICONV_CAST( & inbuf ), & inbytesleft,
2036 & outbuf, & outbytesleft );
2037 if( count == (size_t)(-1) )
2039 if( errno == EILSEQ )
2041 throw Exceptions::ExternalError( "A character converted from UTF-8 could not be converted back to UFT-8." );
2043 else if( errno == EINVAL )
2045 throw Exceptions::ExternalError( "A character converted from UTF-8 was deemed incomplete." );
2047 else if( errno == E2BIG )
2049 throw Exceptions::InternalError( "The buffer allocated for conversion of a single character back to UTF-8 was too small." );
2051 else
2053 std::ostringstream msg;
2054 msg << "iconv failed with an unrecognized error code: " << errno ;
2055 throw Exceptions::InternalError( strrefdup( msg ) );
2058 *outbuf = '\0';
2059 pendingChars << backbuf ;
2062 continue;
2064 catch( const NonLocalExit::NotThisType & ball )
2066 // Never mind, see below
2071 typedef const Lang::Float ArgType;
2072 pendingKerning += Helpers::try_cast_CoreArgument< ArgType >( args.getValue( i ) )->val_;
2073 continue;
2075 catch( const NonLocalExit::NotThisType & ball )
2077 // Never mind, see below
2080 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, i, Helpers::typeSetString( Lang::String::staticTypeName( ), Lang::Float::staticTypeName( ) ) );
2083 if( ! pendingChars.str( ).empty( ) )
2085 res->pushString( RefCountPtr< const Lang::String >( new Lang::String( strrefdup( pendingChars ) ) ) );
2086 pendingChars.str( "" );
2089 Kernel::ContRef cont = evalState->cont_;
2090 cont->takeValue( res,
2091 evalState );
2095 class Core_newrandom : public Lang::CoreFunction
2097 public:
2098 Core_newrandom( const char * title )
2099 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
2101 formals_->appendEvaluatedCoreFormal( "seed", Kernel::THE_SLOT_VARIABLE );
2102 formals_->appendEvaluatedCoreFormal( "size", Helpers::newValHandle( new Lang::Integer( 32 ) ) );
2104 virtual void
2105 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2107 args.applyDefaults( );
2109 typedef const Lang::Integer SizeType;
2110 Lang::Integer::ValueType sz = Helpers::down_cast_CoreArgument< SizeType >( title_, args, 1, callLoc )->val_;
2111 if( sz < 8 )
2113 throw Exceptions::CoreOutOfRange( title_, args, 1, "The size must be at least 8." );
2115 if( sz > 256 )
2117 throw Exceptions::CoreOutOfRange( title_, args, 1, "The size must at most 256." );
2120 size_t argsi = 0;
2124 typedef const Lang::ChronologicalTime SeedType;
2126 RefCountPtr< SeedType > seed = Helpers::try_cast_CoreArgument< SeedType >( args.getValue( argsi ) );
2128 Kernel::ContRef cont = evalState->cont_;
2129 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::HotRandomSeed( sz, seed->val( ) ) ),
2130 evalState );
2131 return;
2133 catch( const NonLocalExit::NotThisType & ball )
2135 // Never mind, see below
2140 typedef const Lang::Integer SeedType;
2142 RefCountPtr< SeedType > seed = Helpers::try_cast_CoreArgument< SeedType >( args.getValue( argsi ) );
2144 Kernel::ContRef cont = evalState->cont_;
2145 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::HotRandomSeed( sz, seed->val_ ) ),
2146 evalState );
2147 return;
2149 catch( const NonLocalExit::NotThisType & ball )
2151 // Never mind, see below
2154 throw Exceptions::CoreTypeMismatch( callLoc, title_, args, argsi, Helpers::typeSetString( Lang::Integer::staticTypeName( ), Lang::ChronologicalTime::staticTypeName( ) ) );
2158 class Core_devrandom : public Lang::CoreFunction
2160 public:
2161 Core_devrandom( const char * title )
2162 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
2164 formals_->appendCoreStateFormal( "device" );
2165 formals_->appendEvaluatedCoreFormal( "size", Helpers::newValHandle( new Lang::Integer( 32 ) ) );
2167 virtual void
2168 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2170 args.applyDefaults( );
2172 typedef const Lang::Integer SizeType;
2173 Lang::Integer::ValueType sz = Helpers::down_cast_CoreArgument< SizeType >( title_, args, 0, callLoc )->val_;
2174 if( sz < 8 )
2176 throw Exceptions::CoreOutOfRange( title_, args, 0, "The size must be at least 8." );
2178 if( sz > 256 )
2180 throw Exceptions::CoreOutOfRange( title_, args, 0, "The size must at most 256." );
2183 typedef Kernel::WarmRandomDevice GeneratorType;
2184 GeneratorType * gen = Helpers::down_cast_CoreState< GeneratorType >( title_, args, 0, callLoc );
2186 Kernel::ContRef cont = evalState->cont_;
2187 cont->takeValue( RefCountPtr< const Lang::Value >( new Lang::HotRandomSeed( static_cast< size_t >( sz ), gen ) ),
2188 evalState );
2192 class Core_destination : public Lang::CoreFunction
2194 public:
2195 Core_destination( const char * title )
2196 : CoreFunction( title, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) )
2198 formals_->appendEvaluatedCoreFormal( "remote", Kernel::THE_FALSE_VARIABLE );
2199 formals_->appendEvaluatedCoreFormal( "name", Kernel::THE_VOID_VARIABLE );
2200 formals_->appendEvaluatedCoreFormal( "level", Kernel::THE_VOID_VARIABLE );
2201 formals_->appendEvaluatedCoreFormal( "text", Kernel::THE_VOID_VARIABLE );
2202 formals_->appendEvaluatedCoreFormal( "open", Kernel::THE_FALSE_VARIABLE );
2203 formals_->appendEvaluatedCoreFormal( "bold", Kernel::THE_FALSE_VARIABLE );
2204 formals_->appendEvaluatedCoreFormal( "italic", Kernel::THE_FALSE_VARIABLE );
2205 formals_->appendEvaluatedCoreFormal( "color", Helpers::newValHandle( new Lang::RGB( Concrete::RGB( 0, 0, 0 ) ) ) );
2206 formals_->appendEvaluatedCoreFormal( "sides", Kernel::THE_VOID_VARIABLE );
2207 formals_->appendEvaluatedCoreFormal( "target", Kernel::THE_VOID_VARIABLE );
2208 formals_->appendEvaluatedCoreFormal( "fittobbox", Kernel::THE_VOID_VARIABLE );
2209 formals_->appendEvaluatedCoreFormal( "zoom", Kernel::THE_VOID_VARIABLE );
2210 formals_->appendEvaluatedCoreFormal( "transform", Kernel::THE_TRUE_VARIABLE );
2212 virtual void
2213 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2215 args.applyDefaults( );
2217 size_t argsi = 0;
2218 const size_t remove_i = argsi;
2219 typedef const Lang::Boolean RemoteType;
2220 bool remote = Helpers::down_cast_CoreArgument< RemoteType >( title_, args, argsi, callLoc )->val_;
2222 ++argsi;
2223 typedef const Lang::String NameType;
2224 RefCountPtr< NameType > nameVal = Helpers::down_cast_CoreArgument< NameType >( title_, args, argsi, callLoc, true );
2225 RefCountPtr< const char > name = RefCountPtr< const char >( NullPtr< const char >( ) );
2226 if( nameVal != NullPtr< NameType >( ) )
2228 const SimplePDF::PDF_Version::Version STRINGDESTS_VERSION = SimplePDF::PDF_Version::PDF_1_2;
2229 if( Kernel::the_PDF_version.greaterOrEqual( STRINGDESTS_VERSION ) )
2231 name = nameVal->val_;
2233 else
2235 Kernel::the_PDF_version.message( STRINGDESTS_VERSION, "The naming of a destination was ignored." );
2236 // Note that this will leave name being null, and hence generate further errors if remote_.
2239 if( nameVal == NullPtr< NameType >( ) ) // Note why this is not an else clause!
2241 if( remote )
2243 throw Exceptions::CoreOutOfRange( title_, args, remove_i, "The destination cannot be remote if no name is given." );
2247 ++argsi;
2248 const size_t outlineLevel_i = argsi;
2249 typedef const Lang::Integer OutlineLevelType;
2250 RefCountPtr< OutlineLevelType > levelVal = Helpers::down_cast_CoreArgument< OutlineLevelType >( title_, args, argsi, callLoc, true );
2251 int outlineLevel = -1; // This will remain negative only if the level is not present.
2252 if( levelVal != NullPtr< OutlineLevelType >( ) )
2254 outlineLevel = levelVal->val_;
2255 if( outlineLevel < 0 )
2257 throw Exceptions::CoreOutOfRange( title_, args, argsi, "The outline level must be non-negative." );
2261 ++argsi;
2262 typedef const Lang::String OutlineTextType;
2263 RefCountPtr< OutlineTextType > textVal = Helpers::down_cast_CoreArgument< OutlineTextType >( title_, args, argsi, callLoc, true );
2264 RefCountPtr< const char > outlineText = RefCountPtr< const char >( NullPtr< const char >( ) );
2265 if( textVal != NullPtr< OutlineTextType >( ) )
2267 outlineText = textVal->val_;
2269 else
2271 if( outlineLevel >= 0 )
2273 throw Exceptions::CoreOutOfRange( title_, args, outlineLevel_i, "Without an outline text, it is not allowed to make an outline item." );
2277 ++argsi;
2278 typedef const Lang::Boolean OutlineOpenType;
2279 bool outlineOpen = Helpers::down_cast_CoreArgument< OutlineOpenType >( title_, args, argsi, callLoc )->val_;
2281 ++argsi;
2282 typedef const Lang::Boolean OutlineBoldType;
2283 bool outlineBold = Helpers::down_cast_CoreArgument< OutlineBoldType >( title_, args, argsi, callLoc )->val_;
2285 ++argsi;
2286 typedef const Lang::Boolean OutlineItalicType;
2287 bool outlineItalic = Helpers::down_cast_CoreArgument< OutlineItalicType >( title_, args, argsi, callLoc )->val_;
2289 ++argsi;
2290 typedef const Lang::RGB OutlineColorType;
2291 Concrete::RGB outlineColor = Helpers::down_cast_CoreArgument< OutlineColorType >( title_, args, argsi, callLoc )->components( );
2293 ++argsi;
2294 const size_t sidesMode_i = argsi;
2295 typedef const Lang::Symbol SidesModeType;
2296 RefCountPtr< SidesModeType > sidesVal = Helpers::down_cast_CoreArgument< SidesModeType >( title_, args, argsi, callLoc, true );
2298 ++argsi;
2299 const size_t target_i = argsi;
2300 typedef const Lang::Drawable2D TargetType;
2301 RefCountPtr< TargetType > target = Helpers::down_cast_CoreArgument< TargetType >( title_, args, argsi, callLoc, true );
2303 Lang::DocumentDestination::Sides sides = Lang::DocumentDestination::PAGE; // Defaults to false, unless a target is given.
2304 if( target != NullPtr< TargetType >( ) )
2306 sides = Lang::DocumentDestination::TOPLEFT;
2307 if( remote )
2309 throw Exceptions::CoreOutOfRange( title_, args, target_i, "The target can not be specified for remote destinations." );
2312 static Lang::Symbol SIDES_TopLeft( "topleft" );
2313 static Lang::Symbol SIDES_Page( "page" );
2314 static Lang::Symbol SIDES_Top( "top" );
2315 static Lang::Symbol SIDES_Left( "left" );
2316 static Lang::Symbol SIDES_Rectangle( "rectangle" );
2317 if( sidesVal != NullPtr< SidesModeType >( ) )
2319 if( *sidesVal == SIDES_TopLeft )
2321 sides = Lang::DocumentDestination::TOPLEFT;
2323 else if( *sidesVal == SIDES_Page )
2325 if( target != NullPtr< TargetType >( ) )
2327 throw Exceptions::CoreOutOfRange( title_, args, sidesMode_i, "The sides mode cannot be page when a target object is present." );
2329 sides = Lang::DocumentDestination::PAGE;
2331 else if( *sidesVal == SIDES_Top )
2333 sides = Lang::DocumentDestination::TOP;
2335 else if( *sidesVal == SIDES_Left )
2337 sides = Lang::DocumentDestination::LEFT;
2339 else if( *sidesVal == SIDES_Rectangle )
2341 sides = Lang::DocumentDestination::RECTANGLE;
2343 else
2345 std::ostringstream oss;
2346 oss << "Valid sides modes are the symbols { "
2347 << SIDES_TopLeft.name( ).getPtr( ) << ", "
2348 << SIDES_Page.name( ).getPtr( ) << ", "
2349 << SIDES_Top.name( ).getPtr( ) << ", "
2350 << SIDES_Left.name( ).getPtr( ) << ", "
2351 << SIDES_Rectangle.name( ).getPtr( )
2352 << " }." ;
2353 throw Exceptions::CoreOutOfRange( title_, args, sidesMode_i, strrefdup( oss ) );
2357 ++argsi;
2358 typedef const Lang::Boolean FitToType;
2359 RefCountPtr< FitToType > fittobboxVal = Helpers::down_cast_CoreArgument< FitToType >( title_, args, argsi, callLoc, true );
2360 bool fittobbox = false;
2361 if( fittobboxVal != NullPtr< FitToType >( ) )
2363 if( remote || sides == Lang::DocumentDestination::TOPLEFT || sides == Lang::DocumentDestination::RECTANGLE )
2365 throw Exceptions::CoreOutOfRange( title_, args, argsi, "The fit-to-bbox flag cannot be specified in this mode." );
2367 fittobbox = fittobboxVal->val_;
2370 ++argsi;
2371 typedef const Lang::Float ZoomType;
2372 RefCountPtr< ZoomType > zoomVal = Helpers::down_cast_CoreArgument< ZoomType >( title_, args, argsi, callLoc, true );
2373 double zoom = 0; // This will remain zero only if the zoom argument is not specified.
2374 if( zoomVal != NullPtr< ZoomType >( ) )
2376 if( remote || sides != Lang::DocumentDestination::TOPLEFT )
2378 throw Exceptions::CoreOutOfRange( title_, args, argsi, "The zoom can only be specified when using the top-left sides." );
2380 zoom = zoomVal->val_;
2381 if( zoom <= 0 )
2383 throw Exceptions::CoreOutOfRange( title_, args, argsi, "The zoom value must be positive." );
2387 ++argsi;
2388 typedef const Lang::Boolean DoTransformType;
2389 bool doTransform = Helpers::down_cast_CoreArgument< DoTransformType >( title_, args, argsi, callLoc )->val_;
2391 Kernel::ContRef cont = evalState->cont_;
2392 if( remote )
2394 RefCountPtr< const Lang::DocumentDestination >
2395 taggedObj( new Lang::DocumentDestination( remote, name, outlineLevel,
2396 outlineText, outlineOpen, outlineBold, outlineItalic, outlineColor ) );
2397 cont->takeValue( RefCountPtr< const Lang::Value >
2398 ( new Lang::TaggedValue2D( Kernel::THE_NAVIGATION_SYMBOL, taggedObj ) ),
2399 evalState );
2401 else
2403 RefCountPtr< const Lang::DocumentDestination >
2404 taggedObj( new Lang::DocumentDestination( name, outlineLevel,
2405 outlineText, outlineOpen, outlineBold, outlineItalic, outlineColor,
2406 sides, target, fittobbox, zoom ) );
2407 if( doTransform )
2409 cont->takeValue( RefCountPtr< const Lang::Value >
2410 ( new Lang::TaggedGeometric2D( Kernel::THE_NAVIGATION_SYMBOL, taggedObj ) ),
2411 evalState );
2413 else
2415 cont->takeValue( RefCountPtr< const Lang::Value >
2416 ( new Lang::TaggedValue2D( Kernel::THE_NAVIGATION_SYMBOL, taggedObj ) ),
2417 evalState );
2427 void
2428 Kernel::registerCore_construct( Kernel::Environment * env )
2430 env->initDefineCoreFunction( new Lang::Core_cons( "cons" ) );
2431 env->initDefineCoreFunction( new Lang::Core_list( "list" ) );
2432 env->initDefineCoreFunction( new Lang::Core_unlist( "unlist" ) );
2433 env->initDefineCoreFunction( new Lang::Core_isnull( "null?" ) );
2434 env->initDefineCoreFunction( new Lang::Core_range( "range" ) );
2435 env->initDefineCoreFunction( new Lang::Core_affinetransform( "affinetransform" ) );
2436 env->initDefineCoreFunction( new Lang::Core_shift( "shift" ) );
2437 env->initDefineCoreFunction( new Lang::Core_rotate( "rotate" ) );
2438 env->initDefineCoreFunction( new Lang::Core_rotate3d( "rotate3D" ) );
2439 env->initDefineCoreFunction( new Lang::Core_scale( "scale" ) );
2440 env->initDefineCoreFunction( new Lang::Core_scale3d( "scale3D" ) );
2441 env->initDefineCoreFunction( new Lang::Core_affinetransform3D( "affinetransform3D" ) );
2442 env->initDefineCoreFunction( new Lang::Core_inverse( "inverse" ) );
2444 env->initDefineCoreFunction( new Lang::Core_formxo( "formxo" ) );
2445 env->initDefineCoreFunction( new Lang::Core_transparencygroup( "tgroup" ) );
2447 env->initDefineCoreFunction( new Lang::Core_tag( "tag" ) );
2448 env->initDefineCoreFunction( new Lang::Core_find( "find" ) );
2449 env->initDefineCoreFunction( new Lang::Core_findall( "findall" ) );
2451 env->initDefineCoreFunction( new Lang::Core_ambient_light( "ambient_light" ) );
2452 env->initDefineCoreFunction( new Lang::Core_specular_light( "specular_light" ) );
2453 env->initDefineCoreFunction( new Lang::Core_distant_light( "distant_light" ) );
2454 env->initDefineCoreFunction( new Lang::Core_phong( "phong" ) );
2456 env->initDefineCoreFunction( new Lang::Core_vector( "vector" ) );
2457 env->initDefineCoreFunction( new Lang::Core_importPDFpages( "import" ) );
2459 env->initDefineCoreFunction( new Lang::Core_svg_path( "svg_path" ) );
2461 env->initDefineCoreFunction( new Lang::Core_sprintf( "sprintf" ) );
2462 env->initDefineCoreFunction( new Lang::Core_strftime( "strftime" ) );
2464 env->initDefineCoreFunction( new Lang::Core_newrandom( "newRandom" ) );
2465 env->initDefineCoreFunction( new Lang::Core_devrandom( "devRandom" ) );
2467 env->initDefineCoreFunction( new Lang::Core_destination( "destination" ) );
2469 env->initDefineCoreFunction( new Lang::Core_textrenderingmode( "textmode" ) );
2470 env->initDefineCoreFunction( new Lang::Core_manualkern( "kerning" ) );
2471 env->initDefineCoreFunction( new Lang::Core_automatickern( "kern" ) );