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, 2009, 2010, 2013, 2014 Henrik Tidefelt
21 #include "Shapes_Helpers_decls.h"
23 #include "coreconstruct_impl.h"
24 #include "singlelistrange.h"
25 #include "shapescore.h"
27 #include "shapesexceptions.h"
29 #include "simplepdfi.h"
30 #include "simplepdfo.h"
33 #include "multipage.h"
34 #include "charconverters.h"
35 #include "pagecontentstates.h"
36 #include "texlabelmanager.h"
37 #include "autoonoff.h"
38 #include "timetypes.h"
39 #include "graphtypes.h"
40 #include "shapesscanner.h"
41 #include "rasterloaders.h"
42 #include "glyphlist.h"
48 #include FT_FREETYPE_H
50 #ifdef HAVE_FONTCONFIG
51 #include <fontconfig/fontconfig.h>
61 using namespace Shapes
;
68 RasterLoader_PNG theRasterLoader_PNG
;
69 RasterLoader_JPEG theRasterLoader_JPEG
;
70 #ifdef HAVE_FONTCONFIG
71 class AutoDestroyFcPattern
75 AutoDestroyFcPattern( FcPattern
* pat
)
78 ~AutoDestroyFcPattern( )
82 FcPatternDestroy( pat_
);
90 class AutoDestroyFcFontSet
94 AutoDestroyFcFontSet( FcFontSet
* set
)
97 ~AutoDestroyFcFontSet( )
101 FcFontSetDestroy( set_
);
115 class Core_tag
: public Lang::CoreFunction
118 Core_tag( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
119 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
121 formals_
->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE
);
122 formals_
->appendEvaluatedCoreFormal( "obj", Kernel::THE_SLOT_VARIABLE
);
123 formals_
->appendEvaluatedCoreFormal( "transform", Kernel::THE_TRUE_VARIABLE
); /* this argument means "transform if applicable" */
124 formals_
->appendEvaluatedCoreFormal( "draw", Kernel::THE_TRUE_VARIABLE
); /* this argument means "draw if applicable" */
128 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
130 args
.applyDefaults( callLoc
);
132 typedef const Lang::Symbol KeyType
;
133 RefCountPtr
< KeyType
> key
= Helpers::down_cast_CoreArgument
< KeyType
>( id_
, args
, 0, callLoc
);
134 bool tryTransform
= Helpers::down_cast_CoreArgument
< const Lang::Boolean
>( id_
, args
, 2, callLoc
)->val_
;
135 bool tryDraw
= Helpers::down_cast_CoreArgument
< const Lang::Boolean
>( id_
, args
, 3, callLoc
)->val_
;
137 if( tryDraw
&& ! tryTransform
)
139 throw Exceptions::CoreOutOfRange( id_
, args
, 3, "A tagged object which does not transform cannot be drawn." );
148 typedef const Lang::Drawable2D ArgType
;
150 RefCountPtr
< ArgType
> obj
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi
) );
152 Kernel::ContRef cont
= evalState
->cont_
;
153 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::TaggedDrawable2D( key
, obj
) ),
157 catch( const NonLocalExit::NotThisType
& ball
)
159 /* Never mind, see below. */
164 typedef const Lang::Drawable3D ArgType
;
166 RefCountPtr
< ArgType
> obj
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi
) );
168 Kernel::ContRef cont
= evalState
->cont_
;
169 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::TaggedDrawable3D( key
, obj
) ),
173 catch( const NonLocalExit::NotThisType
& ball
)
175 /* Never mind, see below. */
183 typedef const Lang::Geometric2D ArgType
;
185 RefCountPtr
< ArgType
> obj
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi
) );
187 Kernel::ContRef cont
= evalState
->cont_
;
188 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::TaggedGeometric2D( key
, obj
) ),
192 catch( const NonLocalExit::NotThisType
& ball
)
194 /* Never mind, see below. */
199 typedef const Lang::Geometric3D ArgType
;
201 RefCountPtr
< ArgType
> obj
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi
) );
203 Kernel::ContRef cont
= evalState
->cont_
;
204 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::TaggedGeometric3D( key
, obj
) ),
208 catch( const NonLocalExit::NotThisType
& ball
)
210 /* Never mind, see below. */
215 // As a last resort, we tag any value.
216 // We return a Drawable2D. Use immerse to make it 3D.
217 Kernel::ContRef cont
= evalState
->cont_
;
218 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::TaggedValue2D( key
, args
.getValue( argsi
) ) ),
224 // This function is in this file just because it i so related to Core_tag.
225 class Core_find
: public Lang::CoreFunction
228 Core_find( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
229 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
231 formals_
->appendEvaluatedCoreFormal( "container", Kernel::THE_SLOT_VARIABLE
);
232 formals_
->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE
);
236 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
238 args
.applyDefaults( callLoc
);
240 typedef const Lang::Symbol KeyType
;
241 RefCountPtr
< KeyType
> key
= Helpers::down_cast_CoreArgument
< KeyType
>( id_
, args
, 1, callLoc
);
247 typedef const Lang::Drawable2D ContainerType
;
249 RefCountPtr
< ContainerType
> container
= Helpers::try_cast_CoreArgument
< ContainerType
>( args
.getValue( argsi
) );
251 if( ! container
->findOneTag( evalState
, key
->getKey( ), Lang::THE_2D_IDENTITY
) )
253 throw Exceptions::CoreOutOfRange( id_
, args
, 1, "Key not found." );
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 if( ! container
->findOneTag( evalState
, key
->getKey( ), Lang::THE_3D_IDENTITY
) )
270 throw Exceptions::CoreOutOfRange( id_
, args
, 1, "Key not found." );
274 catch( const NonLocalExit::NotThisType
& ball
)
276 /* Never mind, see below. */
279 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, argsi
, Helpers::typeSetString( Lang::Drawable2D::staticTypeName( ), Lang::Drawable3D::staticTypeName( ) ) );
283 // This function is in this file just because it i so related to Core_tag.
284 class Core_findall
: public Lang::CoreFunction
287 Core_findall( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
288 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
290 formals_
->appendEvaluatedCoreFormal( "container", Kernel::THE_SLOT_VARIABLE
);
291 formals_
->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE
);
295 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
297 args
.applyDefaults( callLoc
);
299 typedef const Lang::Symbol KeyType
;
300 RefCountPtr
< KeyType
> key
= Helpers::down_cast_CoreArgument
< KeyType
>( id_
, args
, 1, callLoc
);
306 typedef const Lang::Drawable2D ContainerType
;
308 RefCountPtr
< ContainerType
> container
= Helpers::try_cast_CoreArgument
< ContainerType
>( args
.getValue( argsi
) );
310 std::vector
< Kernel::ValueRef
> * dst
= new std::vector
< Kernel::ValueRef
>;
311 container
->findTags( dst
, evalState
->dyn_
, key
->getKey( ), Lang::THE_2D_IDENTITY
);
313 Kernel::ContRef cont
= evalState
->cont_
;
314 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::VectorFunction( dst
) ),
318 catch( const NonLocalExit::NotThisType
& ball
)
320 /* Never mind, see below. */
325 typedef const Lang::Drawable3D ContainerType
;
327 RefCountPtr
< ContainerType
> container
= Helpers::try_cast_CoreArgument
< ContainerType
>( args
.getValue( argsi
) );
329 std::vector
< Kernel::ValueRef
> * dst
= new std::vector
< Kernel::ValueRef
>;
330 container
->findTags( dst
, evalState
->dyn_
, key
->getKey( ), Lang::THE_3D_IDENTITY
);
332 Kernel::ContRef cont
= evalState
->cont_
;
333 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::VectorFunction( dst
) ),
337 catch( const NonLocalExit::NotThisType
& ball
)
339 /* Never mind, see below. */
342 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, argsi
, Helpers::typeSetString( Lang::Drawable2D::staticTypeName( ), Lang::Drawable3D::staticTypeName( ) ) );
346 class Core_phong
: public Lang::CoreFunction
349 Core_phong( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
351 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
353 const size_t ARITY
= 1;
354 CHECK_ARITY( args
, ARITY
, id_
);
356 typedef const Lang::Float ArgType
;
357 double exponent
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, 0, callLoc
)->val_
;
360 throw Exceptions::CoreOutOfRange( id_
, args
, 0, "The Phong exponent should be greater than 0." );
363 Kernel::ContRef cont
= evalState
->cont_
;
364 cont
->takeValue( Kernel::ValueRef( new Lang::SpecularReflectionTerm( 1., exponent
) ),
369 class Core_cons
: public Lang::CoreFunction
372 Core_cons( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
373 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), false ) )
375 formals_
->appendEvaluatedCoreFormal( "car", Kernel::THE_SLOT_VARIABLE
);
376 formals_
->appendEvaluatedCoreFormal( "cdr", Kernel::THE_SLOT_VARIABLE
);
379 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
381 const size_t ARITY
= 2;
382 CHECK_ARITY( args
, ARITY
, id_
);
384 Kernel::VariableHandle cdr
= args
.getHandle( 1 );
385 if( ! cdr
->isThunk( ) ){
386 RefCountPtr
< const Lang::Value
> cdrVal
= cdr
->getUntyped( );
387 RefCountPtr
< const Lang::SingleList
> cdrValTyped
= cdrVal
.down_cast
< const Lang::SingleList
>( );
388 if( cdrValTyped
!= NullPtr
< const Lang::SingleList
>( ) ){
389 Kernel::ContRef cont
= evalState
->cont_
;
390 cont
->takeValue( Kernel::ValueRef( new Lang::SingleListPair( args
.getHandle( 0 ),
397 Kernel::ContRef cont
= evalState
->cont_
;
398 cont
->takeValue( Kernel::ValueRef( new Lang::ConsPair( args
.getHandle( 0 ),
404 class Core_list
: public Lang::CoreFunction
407 Core_list( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
409 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
411 RefCountPtr
< const Lang::SingleList
> res
= Lang::THE_CONS_NULL
;
412 if( ! args
.empty( ) )
414 for( size_t i
= args
.size( ) - 1; ; --i
)
416 res
= RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListPair( args
.getHandle( i
), res
) );
424 Kernel::ContRef cont
= evalState
->cont_
;
425 cont
->takeValue( res
,
430 class Core_unlist
: public Lang::CoreFunction
432 Kernel::UnnamedStructureFactory argListFactory_
;
434 Core_unlist( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
436 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
438 const size_t ARITY
= 1;
439 CHECK_ARITY( args
, ARITY
, id_
);
441 typedef const Lang::SingleList ArgType
;
443 Kernel::ContRef cont
= evalState
->cont_
;
444 cont
->takeValue( argListFactory_
.build( Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, 0, callLoc
) ),
449 class Core_isnil
: public Lang::CoreFunction
452 Core_isnil( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
454 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
456 const size_t ARITY
= 1;
457 CHECK_ARITY( args
, ARITY
, id_
);
459 RefCountPtr
< const Lang::Value
> aUntyped
= args
.getValue( 0 );
461 Kernel::ContRef cont
= evalState
->cont_
;
462 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::Boolean( dynamic_cast< const Lang::SingleListNull
* >( args
.getValue( 0 ).getPtr( ) ) != 0 ) ),
467 class Core_span
: public Lang::CoreFunction
470 Core_span( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
471 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), false ) )
473 formals_
->appendEvaluatedCoreFormal( "begin", Kernel::THE_VOID_VARIABLE
);
474 formals_
->appendEvaluatedCoreFormal( "end", Kernel::THE_VOID_VARIABLE
);
475 formals_
->appendEvaluatedCoreFormal( "step", Kernel::THE_VOID_VARIABLE
);
476 formals_
->appendEvaluatedCoreFormal( "count", Kernel::THE_VOID_VARIABLE
);
479 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
481 args
.applyDefaults( callLoc
);
483 Kernel::ContRef cont
= evalState
->cont_
;
484 cont
->takeValue( Kernel::ValueRef( new Lang::Span( args
.getHandle( 0 ), args
.getHandle( 1 ), args
.getHandle( 2 ), args
.getHandle( 3 ) ) ),
489 class Core_affinetransform
: public Lang::CoreFunction
492 Core_affinetransform( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
494 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
496 const size_t ARITY
= 3;
497 CHECK_ARITY( args
, ARITY
, id_
);
499 typedef const Lang::FloatPair ArgType0
;
500 typedef const Lang::FloatPair ArgType1
;
501 typedef const Lang::Coords2D ArgType2
;
503 RefCountPtr
< ArgType0
> argx
= Helpers::down_cast_CoreArgument
< ArgType0
>( id_
, args
, 0, callLoc
);
504 RefCountPtr
< ArgType1
> argy
= Helpers::down_cast_CoreArgument
< ArgType1
>( id_
, args
, 1, callLoc
);
505 RefCountPtr
< ArgType2
> arg1
= Helpers::down_cast_CoreArgument
< ArgType2
>( id_
, args
, 2, callLoc
);
507 Kernel::ContRef cont
= evalState
->cont_
;
508 cont
->takeValue( Kernel::ValueRef( new Lang::Transform2D( argx
->x_
, argx
->y_
, argy
->x_
, argy
->y_
, arg1
->x_
.get( ), arg1
->y_
.get( ) ) ),
513 class Core_affinetransform3d
: public Lang::CoreFunction
516 Core_affinetransform3d( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
518 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
520 const size_t ARITY
= 4;
521 CHECK_ARITY( args
, ARITY
, id_
);
523 typedef const Lang::FloatTriple ArgType0
;
524 typedef const Lang::FloatTriple ArgType1
;
525 typedef const Lang::FloatTriple ArgType2
;
526 typedef const Lang::Coords3D ArgType3
;
528 RefCountPtr
< ArgType0
> argx
= Helpers::down_cast_CoreArgument
< ArgType0
>( id_
, args
, 0, callLoc
);
529 RefCountPtr
< ArgType1
> argy
= Helpers::down_cast_CoreArgument
< ArgType1
>( id_
, args
, 1, callLoc
);
530 RefCountPtr
< ArgType2
> argz
= Helpers::down_cast_CoreArgument
< ArgType2
>( id_
, args
, 2, callLoc
);
531 RefCountPtr
< ArgType3
> arg1
= Helpers::down_cast_CoreArgument
< ArgType3
>( id_
, args
, 3, callLoc
);
533 Kernel::ContRef cont
= evalState
->cont_
;
534 cont
->takeValue( Kernel::ValueRef( new Lang::Transform3D( argx
->x_
, argx
->y_
, argx
->z_
,
535 argy
->x_
, argy
->y_
, argy
->z_
,
536 argz
->x_
, argz
->y_
, argz
->z_
,
537 arg1
->x_
.get( ), arg1
->y_
.get( ), arg1
->z_
.get( ) ) ),
542 class Core_shift
: public Lang::CoreFunction
545 Core_shift( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
547 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
549 const size_t ARITY
= 1;
550 CHECK_ARITY( args
, ARITY
, id_
);
552 Kernel::ContRef cont
= evalState
->cont_
;
556 typedef const Lang::Coords2D ArgType1
;
557 RefCountPtr
< ArgType1
> arg1
= Helpers::down_cast_CoreArgument
< ArgType1
>( id_
, args
, i
, callLoc
);
558 cont
->takeValue( Kernel::ValueRef( new Lang::Transform2D( 1, 0, 0, 1, arg1
->x_
.get( ), arg1
->y_
.get( ) ) ),
563 class Core_shift3d
: public Lang::CoreFunction
566 Core_shift3d( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
568 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
570 const size_t ARITY
= 1;
571 CHECK_ARITY( args
, ARITY
, id_
);
573 Kernel::ContRef cont
= evalState
->cont_
;
577 typedef const Lang::Coords3D ArgType1
;
578 RefCountPtr
< ArgType1
> arg1
= Helpers::down_cast_CoreArgument
< ArgType1
>( id_
, args
, i
, callLoc
);
579 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( ) ) ),
584 class Core_rotate
: public Lang::CoreFunction
587 Core_rotate( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
588 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
590 formals_
->appendEvaluatedCoreFormal( "angle", Kernel::THE_SLOT_VARIABLE
);
593 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
595 args
.applyDefaults( callLoc
);
599 typedef const Lang::Float ArgType1
;
600 RefCountPtr
< ArgType1
> arg1
= Helpers::down_cast_CoreArgument
< ArgType1
>( id_
, args
, i
, callLoc
);
602 double c
= cos( arg1
->val_
);
603 double s
= sin( arg1
->val_
);
604 Kernel::ContRef cont
= evalState
->cont_
;
605 cont
->takeValue( Kernel::ValueRef( new Lang::Transform2D( c
, s
, -s
, c
, 0, 0 ) ),
610 class Core_rotate3d
: public Lang::CoreFunction
613 Core_rotate3d( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
614 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
616 formals_
->appendEvaluatedCoreFormal( "dir", Kernel::THE_SLOT_VARIABLE
);
617 formals_
->appendEvaluatedCoreFormal( "angle", Kernel::THE_SLOT_VARIABLE
);
620 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
622 args
.applyDefaults( callLoc
);
626 typedef const Lang::FloatTriple ArgType1
;
627 RefCountPtr
< ArgType1
> dir
= Helpers::down_cast_CoreArgument
< ArgType1
>( id_
, args
, i
, callLoc
);
628 if( dir
->x_
== 0 && dir
->y_
== 0 && dir
->z_
== 0 )
630 throw Exceptions::CoreOutOfRange( id_
, args
, i
, "The rotation direction is degenerate, that is (0,0,0)." );
635 typedef const Lang::Float ArgType2
;
636 RefCountPtr
< ArgType2
> angle
= Helpers::down_cast_CoreArgument
< ArgType2
>( id_
, args
, i
, callLoc
);
638 double r
= sqrt( dir
->x_
* dir
->x_
+ dir
->y_
* dir
->y_
+ dir
->z_
* dir
->z_
);
639 double x
= dir
->x_
/ r
;
640 double y
= dir
->y_
/ r
;
641 double z
= dir
->z_
/ r
;
645 double c
= cos( angle
->val_
);
646 double s
= sin( angle
->val_
);
647 Kernel::ContRef cont
= evalState
->cont_
;
648 cont
->takeValue( Kernel::ValueRef( new Lang::Transform3D( x2
+(y2
+z2
)*c
, x
*y
*(1-c
)+z
*s
, x
*z
*(1-c
)-y
*s
,
649 x
*y
*(1-c
)-z
*s
, y2
+(x2
+z2
)*c
, y
*z
*(1-c
)+x
*s
,
650 x
*z
*(1-c
)+y
*s
, y
*z
*(1-c
)-x
*s
, z2
+(x2
+y2
)*c
,
656 class Core_scale
: public Lang::CoreFunction
659 Core_scale( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
660 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
662 Kernel::VariableHandle
one( new Kernel::Variable( RefCountPtr
< const Lang::Value
>( new Lang::Float( 1 ) ) ) );
664 formals_
->appendEvaluatedCoreFormal( "r", one
);
665 formals_
->appendEvaluatedCoreFormal( "x", one
);
666 formals_
->appendEvaluatedCoreFormal( "y", one
);
669 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
671 args
.applyDefaults( callLoc
);
673 typedef const Lang::Float ArgType
;
674 RefCountPtr
< ArgType
> argr
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, 0, callLoc
);
675 RefCountPtr
< ArgType
> argx
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, 1, callLoc
);
676 RefCountPtr
< ArgType
> argy
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, 2, callLoc
);
678 Kernel::ContRef cont
= evalState
->cont_
;
679 cont
->takeValue( Kernel::ValueRef( new Lang::Transform2D( argr
->val_
* argx
->val_
, 0,
680 0, argr
->val_
* argy
->val_
,
686 class Core_scale3d
: public Lang::CoreFunction
689 Core_scale3d( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
690 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
692 Kernel::VariableHandle
one( new Kernel::Variable( RefCountPtr
< const Lang::Value
>( new Lang::Float( 1 ) ) ) );
694 formals_
->appendEvaluatedCoreFormal( "r", one
);
695 formals_
->appendEvaluatedCoreFormal( "x", one
);
696 formals_
->appendEvaluatedCoreFormal( "y", one
);
697 formals_
->appendEvaluatedCoreFormal( "z", one
);
700 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
702 args
.applyDefaults( callLoc
);
704 typedef const Lang::Float ArgType
;
705 RefCountPtr
< ArgType
> argr
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, 0, callLoc
);
706 RefCountPtr
< ArgType
> argx
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, 1, callLoc
);
707 RefCountPtr
< ArgType
> argy
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, 2, callLoc
);
708 RefCountPtr
< ArgType
> argz
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, 3, callLoc
);
710 Kernel::ContRef cont
= evalState
->cont_
;
711 cont
->takeValue( Kernel::ValueRef( new Lang::Transform3D( argr
->val_
* argx
->val_
, 0, 0,
712 0, argr
->val_
* argy
->val_
, 0,
713 0, 0, argr
->val_
* argz
->val_
,
719 class Core_inverse
: public Lang::CoreFunction
722 Core_inverse( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
724 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
726 const size_t ARITY
= 1;
727 CHECK_ARITY( args
, ARITY
, id_
);
731 typedef const Lang::Transform2D ArgType1
;
732 RefCountPtr
< ArgType1
> tf
= Helpers::down_cast_CoreArgument
< ArgType1
>( id_
, args
, i
, callLoc
);
733 double det
= tf
->xx_
* tf
->yy_
- tf
->xy_
* tf
->yx_
;
734 if( fabs( det
) < Computation::SINGULAR_TRANSFORM_LIMIT
)
736 throw Exceptions::CoreOutOfRange( id_
, args
, 0, "Singular transforms cannot be inverted." );
738 double idet
= 1 / det
;
739 double ixx
= idet
* tf
->yy_
;
740 double ixy
= - idet
* tf
->xy_
;
741 double iyx
= - idet
* tf
->yx_
;
742 double iyy
= idet
* tf
->xx_
;
743 Kernel::ContRef cont
= evalState
->cont_
;
744 cont
->takeValue( Kernel::ValueRef( new Lang::Transform2D( ixx
, iyx
,
746 -( ixx
* tf
->xt_
+ ixy
* tf
->yt_
), -( iyx
* tf
->xt_
+ iyy
* tf
->yt_
) ) ),
751 class Core_inverse3d
: public Lang::CoreFunction
754 Core_inverse3d( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
756 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
758 const size_t ARITY
= 1;
759 CHECK_ARITY( args
, ARITY
, id_
);
763 typedef const Lang::Transform3D ArgType1
;
764 RefCountPtr
< ArgType1
> tf
= Helpers::down_cast_CoreArgument
< ArgType1
>( id_
, args
, i
, callLoc
);
766 tf
->xx_
* ( tf
->yy_
* tf
->zz_
- tf
->yz_
* tf
->zy_
)
767 - tf
->xy_
* ( tf
->yx_
* tf
->zz_
- tf
->yz_
* tf
->zx_
)
768 + tf
->xz_
* ( tf
->yx_
* tf
->zy_
- tf
->yy_
* tf
->zx_
);
769 if( fabs( det
) < Computation::SINGULAR_TRANSFORM_LIMIT
)
771 throw Exceptions::CoreOutOfRange( id_
, args
, 0, "Singular transforms cannot be inverted." );
773 double idet
= 1 / det
;
774 double ixx
= idet
* ( tf
->yy_
* tf
->zz_
- tf
->yz_
* tf
->zy_
);
775 double ixy
= - idet
* ( tf
->xy_
* tf
->zz_
- tf
->xz_
* tf
->zy_
);
776 double ixz
= idet
* ( tf
->xy_
* tf
->yz_
- tf
->xz_
* tf
->yy_
);
777 double iyx
= - idet
* ( tf
->yx_
* tf
->zz_
- tf
->yz_
* tf
->zx_
);
778 double iyy
= idet
* ( tf
->xx_
* tf
->zz_
- tf
->xz_
* tf
->zx_
);
779 double iyz
= - idet
* ( tf
->xx_
* tf
->yz_
- tf
->xz_
* tf
->yx_
);
780 double izx
= idet
* ( tf
->yx_
* tf
->zy_
- tf
->yy_
* tf
->zx_
);
781 double izy
= - idet
* ( tf
->xx_
* tf
->zy_
- tf
->xy_
* tf
->zx_
);
782 double izz
= idet
* ( tf
->xx_
* tf
->yy_
- tf
->xy_
* tf
->yx_
);
783 Kernel::ContRef cont
= evalState
->cont_
;
784 cont
->takeValue( Kernel::ValueRef( new Lang::Transform3D( ixx
, iyx
, izx
,
787 -( ixx
* tf
->xt_
+ ixy
* tf
->yt_
+ ixz
* tf
->zt_
),
788 -( iyx
* tf
->xt_
+ iyy
* tf
->yt_
+ iyz
* tf
->zt_
),
789 -( izx
* tf
->xt_
+ izy
* tf
->yt_
+ izz
* tf
->zt_
) ) ),
794 class Core_formxo
: public Lang::CoreFunction
797 Core_formxo( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
799 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
801 const size_t ARITY
= 1;
802 CHECK_ARITY( args
, ARITY
, id_
);
804 typedef const Lang::Drawable2D ArgType
;
805 RefCountPtr
< ArgType
> arg
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, 0, callLoc
);
807 RefCountPtr
< const Lang::ElementaryPath2D
> theBBox
= arg
->bbox( Lang::Drawable2D::BOUNDING
);
808 Concrete::Coords2D
llcorner( 0, 0 );
809 Concrete::Coords2D
urcorner( 0, 0 );
810 if( ! theBBox
->boundingRectangle( & llcorner
, & urcorner
) )
812 throw Exceptions::InternalErrorIn( id_
, "The object has no bounding box." );
816 RefCountPtr
< SimplePDF::PDF_Stream_out
> form
;
817 RefCountPtr
< SimplePDF::PDF_Object
> indirection
= SimplePDF::indirect( form
, & Kernel::theIndirectObjectCount
);
819 RefCountPtr
< SimplePDF::PDF_Resources
> resources
;
820 (*form
)[ "Resources" ] = SimplePDF::indirect( resources
, & Kernel::theIndirectObjectCount
);
822 (*form
)[ "Subtype" ] = SimplePDF::newName( "Form" );
823 (*form
)[ "FormType" ] = SimplePDF::newInt( 1 );
824 (*form
)[ "BBox" ] = RefCountPtr
< SimplePDF::PDF_Vector
>( new SimplePDF::PDF_Vector( llcorner
.x_
.offtype
< 1, 0 >( ), llcorner
.y_
.offtype
< 1, 0 >( ),
825 urcorner
.x_
.offtype
< 1, 0 >( ), urcorner
.y_
.offtype
< 1, 0 >( ) ) );
827 /* There's a possibility of adding a transformation matrix entry in the dictionary here, but it is not used, not even
828 * for transformed drawables.
830 // (*markForm)[ "Matrix" ] = RefCountPtr<PDF_Object>( new PDF_Vector( 1, 0, 0, 1, -30, -30 ) );
832 Kernel::PageContentStates
pdfState( resources
);
833 arg
->shipout( form
->data
, & pdfState
, Lang::Transform2D( 1, 0, 0, 1, 0, 0 ) );
836 Lang::XObject
* res
= new Lang::XObject( indirection
,
838 res
->setDebugStr( "user form" );
839 Kernel::ContRef cont
= evalState
->cont_
;
840 cont
->takeValue( Kernel::ValueRef( res
),
845 class Core_transparencygroup
: public Lang::CoreFunction
848 Core_transparencygroup( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
849 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
851 formals_
->appendEvaluatedCoreFormal( "content", Kernel::THE_SLOT_VARIABLE
);
852 formals_
->appendEvaluatedCoreFormal( "isolated", Kernel::THE_FALSE_VARIABLE
);
853 formals_
->appendEvaluatedCoreFormal( "knockout", Kernel::THE_FALSE_VARIABLE
);
856 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
858 args
.applyDefaults( callLoc
);
860 typedef const Lang::Group2D ArgType0
;
861 typedef const Lang::Boolean ArgType1
;
862 typedef const Lang::Boolean ArgType2
;
863 RefCountPtr
< ArgType0
> content
= Helpers::down_cast_CoreArgument
< ArgType0
>( id_
, args
, 0, callLoc
);
864 RefCountPtr
< ArgType1
> isolated
= Helpers::down_cast_CoreArgument
< ArgType1
>( id_
, args
, 1, callLoc
);
865 RefCountPtr
< ArgType2
> knockout
= Helpers::down_cast_CoreArgument
< ArgType2
>( id_
, args
, 2, callLoc
);
867 RefCountPtr
< const Lang::ColorSpace
> blendSpace
= evalState
->dyn_
->getBlendSpace( );
869 Kernel::ContRef cont
= evalState
->cont_
;
870 cont
->takeValue( Helpers::newTransparencyGroup( content
, isolated
->val_
, knockout
->val_
, blendSpace
),
875 class Core_importRasterImage
: public Lang::CoreFunction
877 std::map
< const char *, const Helpers::RasterLoader
*, charPtrLess
> loaders_
;
879 Core_importRasterImage( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
880 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
882 formals_
->appendEvaluatedCoreFormal( "filename", Kernel::THE_SLOT_VARIABLE
);
883 formals_
->appendEvaluatedCoreFormal( "resolution", Helpers::newValHandle( new Lang::Length( Concrete::Length( 1 ) ) ) );
884 formals_
->appendEvaluatedCoreFormal( "override", Kernel::THE_TRUE_VARIABLE
);
885 formals_
->appendEvaluatedCoreFormal( "kind", Kernel::THE_VOID_VARIABLE
);
887 loaders_
[ "png" ] = & Helpers::theRasterLoader_PNG
;
888 loaders_
[ "PNG" ] = & Helpers::theRasterLoader_PNG
;
890 loaders_
[ "jpg" ] = & Helpers::theRasterLoader_JPEG
;
891 loaders_
[ "JPG" ] = & Helpers::theRasterLoader_JPEG
;
892 loaders_
[ "jpeg" ] = & Helpers::theRasterLoader_JPEG
;
893 loaders_
[ "JPEG" ] = & Helpers::theRasterLoader_JPEG
;
895 /* It would seem natural to also support "JIF"-images, but currently the JPEG library we use won't open such files.
899 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
901 args
.applyDefaults( callLoc
);
905 typedef const Lang::String ArgType
;
906 RefCountPtr
< ArgType
> filename
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, argsi
, callLoc
);
907 size_t argsi_filename
= argsi
;
909 std::string full_filename
;
912 full_filename
= Ast::theShapesScanner
.searchFile( filename
->val_
.getPtr( ), true ); /* true means that errors should be handled in "runtime mode". */
914 catch( RefCountPtr
< const char > & msg
)
916 throw Exceptions::CoreOutOfRange( id_
, args
, argsi_filename
, msg
);
919 RefCountPtr
< std::ifstream
> iFile( new std::ifstream( full_filename
.c_str( ) ) );
920 if( ! iFile
->good( ) )
922 std::ostringstream msg
;
923 msg
<< "Failed to open file for input: " << full_filename
.c_str( ) ;
924 throw Exceptions::CoreOutOfRange( id_
, args
, argsi_filename
, strrefdup( msg
) );
928 typedef const Lang::Length ResolutionType
;
929 Concrete::Length resolution
= Helpers::down_cast_CoreArgument
< ResolutionType
>( id_
, args
, argsi
, callLoc
)->get( );
930 if( resolution
<= Concrete::ZERO_LENGTH
)
932 throw Exceptions::CoreOutOfRange( id_
, args
, argsi
, strrefdup( "The resolution must be positive." ) );
936 typedef const Lang::Boolean OverrideType
;
937 bool override
= Helpers::down_cast_CoreArgument
< OverrideType
>( id_
, args
, argsi
, callLoc
)->val_
;
940 typedef const Lang::Symbol KindType
;
941 RefCountPtr
< KindType
> kind
= Helpers::down_cast_CoreArgument
< KindType
>( id_
, args
, argsi
, callLoc
, true );
942 const Helpers::RasterLoader
* loader
= 0;
943 if( kind
== NullPtr
< KindType
>( ) )
945 const char * begin
= filename
->val_
.getPtr( );
946 const char * ext
= filename
->val_
.getPtr( ) + filename
->bytecount_
- 1;
947 for( ; ext
> begin
; --ext
)
951 typedef typeof loaders_ MapType
;
952 MapType::const_iterator i
= loaders_
.find( ext
+ 1 );
953 if( i
== loaders_
.end( ) )
955 std::ostringstream msg
;
956 msg
<< "Filename extension '" << ext
<< "' has no associated raster loader." ;
957 throw Exceptions::CoreOutOfRange( id_
, args
, argsi_filename
, strrefdup( msg
) );
965 std::ostringstream msg
;
966 msg
<< "Filename without extension must be combined with explicit file kind: " << filename
->val_
.getPtr( ) ;
967 throw Exceptions::CoreOutOfRange( id_
, args
, argsi_filename
, strrefdup( msg
) );
972 static Lang::Symbol
PNG( "PNG" );
973 static Lang::Symbol
JPEG( "JPEG" );
976 loader
= & Helpers::theRasterLoader_PNG
;
978 else if( *kind
== JPEG
)
980 loader
= & Helpers::theRasterLoader_JPEG
;
984 std::ostringstream msg
;
985 msg
<< "The only allowed file kind symbols are { " ;
990 throw Exceptions::CoreOutOfRange( id_
, args
, argsi
, strrefdup( msg
) );
994 Kernel::ContRef cont
= evalState
->cont_
;
995 cont
->takeValue( loader
->load( iFile
, full_filename
, resolution
, override
, id_
, callLoc
),
1000 class Core_vector
: public Lang::CoreFunction
1003 Core_vector( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
1005 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1007 std::vector
< RefCountPtr
< const Lang::Value
> > * res
= new std::vector
< RefCountPtr
< const Lang::Value
> >;
1008 res
->reserve( args
.size( ) );
1010 for( size_t i
= 0; i
!= args
.size( ); ++i
)
1012 res
->push_back( args
.getValue( i
) );
1015 Kernel::ContRef cont
= evalState
->cont_
;
1016 cont
->takeValue( Kernel::ValueRef( new Lang::VectorFunction( res
) ),
1021 class Core_graph
: public Lang::CoreFunction
1024 Core_graph( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
1025 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
1027 formals_
->appendEvaluatedCoreFormal( "nodes", Kernel::THE_NIL_VARIABLE
);
1028 formals_
->appendEvaluatedCoreFormal( "edges", Kernel::THE_NIL_VARIABLE
);
1029 formals_
->appendEvaluatedCoreFormal( "directed", Kernel::THE_FALSE_VARIABLE
);
1030 formals_
->appendEvaluatedCoreFormal( "undirected", Kernel::THE_FALSE_VARIABLE
);
1031 formals_
->appendEvaluatedCoreFormal( "loops", Kernel::THE_FALSE_VARIABLE
);
1032 formals_
->appendEvaluatedCoreFormal( "parallel", Kernel::THE_FALSE_VARIABLE
);
1033 formals_
->appendEvaluatedCoreFormal( "partitions", Kernel::THE_VOID_VARIABLE
);
1036 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1038 args
.applyDefaults( callLoc
);
1041 size_t nodesi
= argsi
;
1042 RefCountPtr
< const Lang::Value
> nodes
= args
.getValue( argsi
);
1044 size_t edgesi
= argsi
;
1045 RefCountPtr
< const Lang::Value
> edges
= args
.getValue( argsi
);
1047 Kernel::GraphDomain
* domainPtr
= new Kernel::GraphDomain( );
1048 RefCountPtr
< const Kernel::GraphDomain
> domain
= RefCountPtr
< const Kernel::GraphDomain
>( domainPtr
);
1049 typedef const Lang::Boolean FlagType
;
1051 if( Helpers::down_cast_CoreArgument
< FlagType
>( id_
, args
, argsi
, callLoc
)->val_
){
1052 domainPtr
->allowDirected( );
1055 if( Helpers::down_cast_CoreArgument
< FlagType
>( id_
, args
, argsi
, callLoc
)->val_
){
1056 domainPtr
->allowUndirected( );
1059 if( Helpers::down_cast_CoreArgument
< FlagType
>( id_
, args
, argsi
, callLoc
)->val_
){
1060 domainPtr
->allowLoops( );
1063 if( Helpers::down_cast_CoreArgument
< FlagType
>( id_
, args
, argsi
, callLoc
)->val_
){
1064 domainPtr
->allowParallel( );
1068 size_t partitionsi
= argsi
;
1069 RefCountPtr
< const Lang::Value
> partitions
= args
.getValue( argsi
);
1071 if( partitions
== Lang::THE_VOID
){
1072 RefCountPtr
< const Lang::SingleList
> noPartitions
= RefCountPtr
< const Lang::SingleList
>( NullPtr
< const Lang::SingleList
>( ) );
1073 evalState
->cont_
= Kernel::ContRef( new Kernel::ForcingListContinuation
1074 ( Kernel::ContRef( new Kernel::Core_graph_cont_nodes( edges
, args
.getLoc( edgesi
), domain
, noPartitions
, evalState
->cont_
, args
.getLoc( partitionsi
), args
.getLoc( nodesi
) ) ),
1075 args
.getLoc( nodesi
),
1077 Kernel::ContRef cont
= evalState
->cont_
;
1078 cont
->takeValue( nodes
, evalState
);
1080 evalState
->cont_
= Kernel::ContRef( new Kernel::ForcingListContinuation
1081 ( Kernel::ContRef( new Kernel::Core_graph_cont_partitions( nodes
, args
.getLoc( nodesi
), edges
, args
.getLoc( edgesi
), domain
, evalState
->cont_
, args
.getLoc( partitionsi
) ) ),
1082 args
.getLoc( partitionsi
),
1084 Kernel::ContRef cont
= evalState
->cont_
;
1085 cont
->takeValue( partitions
, evalState
);
1090 class Core_walk
: public Lang::CoreFunction
1093 Core_walk( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
1094 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
1096 formals_
->appendEvaluatedCoreFormal( "edges", Kernel::THE_NIL_VARIABLE
);
1097 formals_
->appendEvaluatedCoreFormal( "start", Kernel::THE_VOID_VARIABLE
);
1098 formals_
->appendEvaluatedCoreFormal( "end", Kernel::THE_VOID_VARIABLE
);
1101 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1103 args
.applyDefaults( callLoc
);
1106 typedef const Lang::SingleList ListType
;
1107 size_t edgesi
= argsi
;
1108 RefCountPtr
< ListType
> edges
= Helpers::down_cast_CoreArgument
< ListType
>( id_
, args
, argsi
, callLoc
);
1111 typedef const Lang::Node NodeType
;
1112 /* The start and end may be null pointers, and it is not until the Lang::Graph constructor that
1113 * these will be replaced by automatically determined nodes.
1115 RefCountPtr
< NodeType
> start
= Helpers::down_cast_CoreArgument
< NodeType
>( id_
, args
, argsi
, callLoc
, true );
1118 size_t endi
= argsi
;
1119 RefCountPtr
< NodeType
> end
= Helpers::down_cast_CoreArgument
< NodeType
>( id_
, args
, argsi
, callLoc
, true );
1121 RefCountPtr
< const Lang::Graph
> graph
= RefCountPtr
< const Lang::Graph
>( NullPtr
< const Lang::Graph
>( ) );
1122 if( start
!= NullPtr
< const Lang::Node
>( ) ){
1123 graph
= start
->graph( );
1124 if( end
!= NullPtr
< const Lang::Node
>( ) &&
1125 end
->graph( ) != graph
){
1126 throw Exceptions::CoreRequirement( "The end node must belong to the same graph as the start node.", id_
, args
.getLoc( endi
) );
1128 }else if( end
!= NullPtr
< const Lang::Node
>( ) ){
1129 graph
= end
->graph( );
1130 }else if( const Lang::SingleListPair
* ptr
= dynamic_cast< const Lang::SingleListPair
* >( edges
.getPtr( ) ) ){
1131 RefCountPtr
< const Lang::Value
> firstEdgeVal
= ptr
->car_
->getUntyped( );
1132 const Lang::Edge
* firstEdge
= dynamic_cast< const Lang::Edge
* >( firstEdgeVal
.getPtr( ) );
1133 if( firstEdge
== 0 ){
1134 throw Exceptions::TypeMismatch( callLoc
, "First edge", firstEdgeVal
->getTypeName( ), Lang::Edge::staticTypeName( ) );
1136 graph
= firstEdge
->graph( );
1138 throw Exceptions::CoreRequirement( "An empty walk must be specified with a start or end node.", id_
, callLoc
);
1141 evalState
->cont_
= Kernel::ContRef( new Kernel::ForcingListContinuation
1142 ( Kernel::ContRef( new Kernel::Core_walk_cont_edges( graph
, start
, end
, args
.getLoc( edgesi
), evalState
->cont_
, callLoc
) ),
1143 args
.getLoc( edgesi
),
1145 Kernel::ContRef cont
= evalState
->cont_
;
1146 cont
->takeValue( edges
, evalState
);
1150 class Core_interpolate
: public Lang::CoreFunction
1153 Core_interpolate( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
1154 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
1156 formals_
->appendEvaluatedCoreFormal( "function", Kernel::THE_SLOT_VARIABLE
);
1157 formals_
->appendEvaluatedCoreFormal( "domain", Kernel::THE_SLOT_VARIABLE
);
1158 formals_
->appendEvaluatedCoreFormal( "size", Kernel::THE_SLOT_VARIABLE
);
1159 formals_
->appendEvaluatedCoreFormal( "range", Kernel::THE_SLOT_VARIABLE
);
1160 formals_
->appendEvaluatedCoreFormal( "encode", Kernel::THE_VOID_VARIABLE
);
1161 formals_
->appendEvaluatedCoreFormal( "decode", Kernel::THE_VOID_VARIABLE
);
1164 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1166 args
.applyDefaults( callLoc
);
1168 throw Exceptions::NotImplemented( "Core_interpolate::call" );
1172 class Core_importPDFpages
: public Lang::CoreFunction
1175 Core_importPDFpages( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
1177 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1179 const size_t ARITY
= 1;
1180 CHECK_ARITY( args
, ARITY
, id_
);
1182 typedef const Lang::String ArgType
;
1183 RefCountPtr
< ArgType
> arg
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, 0, callLoc
);
1185 std::string filename
;
1188 filename
= Ast::theShapesScanner
.searchFile( arg
->val_
.getPtr( ), true ); /* true means that errors should be handled in "runtime mode". */
1190 catch( RefCountPtr
< const char > & msg
)
1192 throw Exceptions::CoreOutOfRange( id_
, args
, 0, msg
);
1195 RefCountPtr
< std::ifstream
> iFile( new std::ifstream( filename
.c_str( ) ) );
1196 if( ! iFile
->good( ) )
1198 std::ostringstream msg
;
1199 msg
<< "Failed to open file for input: " << arg
->val_
.getPtr( ) ;
1200 throw Exceptions::CoreOutOfRange( id_
, args
, 0, strrefdup( msg
) );
1202 RefCountPtr
< SimplePDF::PDF_in
> pdfi( new SimplePDF::PDF_in( iFile
) );
1204 RefCountPtr
< const std::vector
< RefCountPtr
< const Lang::XObject
> > > typedRes
= RefCountPtr
< const std::vector
< RefCountPtr
< const Lang::XObject
> > >( NullPtr
< std::vector
< RefCountPtr
< const Lang::XObject
> > >( ) );
1207 typedRes
= Kernel::thePDFImporter
.addPagesAsXObjects( pdfi
);
1209 catch( const char * ball
)
1211 throw Exceptions::InternalError( strrefdup( ( std::string( "An error occurred while importing " ) + arg
->val_
.getPtr( ) + ": " + ball
).c_str( ) ) );
1214 std::vector
< RefCountPtr
< const Lang::Value
> > * untypedRes
= new std::vector
< RefCountPtr
< const Lang::Value
> >;
1215 untypedRes
->reserve( typedRes
->size( ) );
1216 typedef typeof *typedRes ListType
;
1217 for( ListType::const_iterator i
= typedRes
->begin( ); i
!= typedRes
->end( ); ++i
)
1219 untypedRes
->push_back( *i
);
1222 Kernel::ContRef cont
= evalState
->cont_
;
1223 cont
->takeValue( Kernel::ValueRef( new Lang::VectorFunction( untypedRes
) ),
1228 namespace Implementation
1231 svg_path_strtod( const char ** src
)
1233 const char * start
= *src
;
1235 double res
= strtod( start
, & endp
);
1239 for( ; *start
== ' '; ++start
)
1241 throw std::string( start
, strchr( start
, ' ' ) - start
);
1246 class Core_svg_path
: public Lang::CoreFunction
1249 Core_svg_path( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
1250 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
1252 formals_
->appendEvaluatedCoreFormal( "d", Kernel::THE_SLOT_VARIABLE
);
1253 formals_
->appendEvaluatedCoreFormal( "xunit", Helpers::newValHandle( new Lang::Length( Concrete::Length( 1 ) ) ) );
1254 formals_
->appendEvaluatedCoreFormal( "yunit", Helpers::newValHandle( new Lang::Length( Concrete::Length( 1 ) ) ) );
1255 formals_
->appendEvaluatedCoreFormal( "multi", Kernel::THE_VOID_VARIABLE
);
1256 formals_
->appendEvaluatedCoreFormal( "singletons", Kernel::THE_TRUE_VARIABLE
);
1259 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1261 args
.applyDefaults( callLoc
);
1264 typedef const Lang::String StrType
;
1265 RefCountPtr
< StrType
> arg
= Helpers::down_cast_CoreArgument
< StrType
>( id_
, args
, argsi
, callLoc
);
1267 typedef const Lang::Length ScaleType
;
1269 Concrete::Length dx
= Helpers::down_cast_CoreArgument
< ScaleType
>( id_
, args
, argsi
, callLoc
)->get( );
1271 Concrete::Length dy
= Helpers::down_cast_CoreArgument
< ScaleType
>( id_
, args
, argsi
, callLoc
)->get( );
1273 typedef const Lang::Boolean FlagType
;
1275 RefCountPtr
< FlagType
> multi
= Helpers::down_cast_CoreArgument
< FlagType
>( id_
, args
, argsi
, callLoc
, true );
1277 bool singletons
= Helpers::down_cast_CoreArgument
< FlagType
>( id_
, args
, argsi
, callLoc
)->val_
;
1279 RefCountPtr
< char > buf
= RefCountPtr
< char >( new char[ 2 * strlen( arg
->val_
.getPtr( ) + 1 ) ] );
1281 /* Get rid of any whitespace that isn't a plain space, and make sure every number is terminated by whitespace.
1283 char * dst
= buf
.getPtr( );
1284 for( const char * src
= arg
->val_
.getPtr( ); *src
!= '\0'; ++src
, ++dst
)
1294 if( ( 'A' <= *src
&& *src
<= 'Z' ) || ( 'a' <= *src
&& *src
<= 'z' ) )
1296 /* Insert whitespace before command to ensure command is not immediately following number.
1308 RefCountPtr
< Lang::MultiPath2D
> multiPath
= RefCountPtr
< Lang::MultiPath2D
>( new Lang::MultiPath2D
);
1309 RefCountPtr
< Lang::ElementaryPath2D
> elemPath
= RefCountPtr
< Lang::ElementaryPath2D
>( NullPtr
< Lang::ElementaryPath2D
>( ) );
1314 Concrete::PathPoint2D
originPathPoint( new Concrete::Coords2D( 0, 0 ) );
1315 Concrete::PathPoint2D
* first
= & originPathPoint
;
1316 Concrete::PathPoint2D
* last
= & originPathPoint
;
1317 const char * srcEnd
= buf
.getPtr( ) + strlen( buf
.getPtr( ) );
1318 for( const char * src
= buf
.getPtr( ); src
< srcEnd
; ++src
)
1320 for( ; *src
== ' '; ++src
)
1354 throw Exceptions::CoreOutOfRange( id_
, args
, 0, strrefdup( std::string( "SVG path command not compatible with cubic splines: " ) + *src
) );
1361 if( elemPath
!= NullPtr
< Lang::ElementaryPath2D
>( ) && ( singletons
|| elemPath
->duration( ) >= 1 ) )
1363 multiPath
->push_back( elemPath
);
1365 Concrete::Length x
= dx
* Implementation::svg_path_strtod( & src
);
1366 Concrete::Length y
= - dy
* Implementation::svg_path_strtod( & src
);
1367 first
= new Concrete::PathPoint2D( new Concrete::Coords2D( x
, y
) );
1369 elemPath
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D
);
1370 elemPath
->push_back( last
);
1376 if( elemPath
!= NullPtr
< Lang::ElementaryPath2D
>( ) && ( singletons
|| elemPath
->duration( ) >= 1 ) )
1378 multiPath
->push_back( elemPath
);
1380 Concrete::Length x
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1381 Concrete::Length y
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1382 first
= new Concrete::PathPoint2D( new Concrete::Coords2D( x
, y
) );
1384 elemPath
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D
);
1385 elemPath
->push_back( last
);
1403 Concrete::Length x
= dx
* Implementation::svg_path_strtod( & src
);
1404 Concrete::Length y
= - dy
* Implementation::svg_path_strtod( & src
);
1405 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x
, y
) );
1406 elemPath
->push_back( last
);
1411 Concrete::Length x
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1412 Concrete::Length y
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1413 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x
, y
) );
1414 elemPath
->push_back( last
);
1419 Concrete::Length x
= dx
* Implementation::svg_path_strtod( & src
);
1420 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x
, last
->mid_
->y_
) );
1421 elemPath
->push_back( last
);
1426 Concrete::Length x
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1427 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x
, last
->mid_
->y_
) );
1428 elemPath
->push_back( last
);
1433 Concrete::Length y
= - dy
* Implementation::svg_path_strtod( & src
);
1434 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( last
->mid_
->x_
, y
) );
1435 elemPath
->push_back( last
);
1440 Concrete::Length y
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1441 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( last
->mid_
->x_
, y
) );
1442 elemPath
->push_back( last
);
1447 Concrete::Length x1
= dx
* Implementation::svg_path_strtod( & src
);
1448 Concrete::Length y1
= - dy
* Implementation::svg_path_strtod( & src
);
1449 Concrete::Length x2
= dx
* Implementation::svg_path_strtod( & src
);
1450 Concrete::Length y2
= - dy
* Implementation::svg_path_strtod( & src
);
1451 Concrete::Length x3
= dx
* Implementation::svg_path_strtod( & src
);
1452 Concrete::Length y3
= - dy
* Implementation::svg_path_strtod( & src
);
1453 last
->front_
= new Concrete::Coords2D( x1
, y1
);
1454 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x3
, y3
) );
1455 last
->rear_
= new Concrete::Coords2D( x2
, y2
);
1456 elemPath
->push_back( last
);
1461 Concrete::Length x1
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1462 Concrete::Length y1
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1463 Concrete::Length x2
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1464 Concrete::Length y2
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1465 Concrete::Length x3
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1466 Concrete::Length y3
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1467 last
->front_
= new Concrete::Coords2D( x1
, y1
);
1468 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x3
, y3
) );
1469 last
->rear_
= new Concrete::Coords2D( x2
, y2
);
1470 elemPath
->push_back( last
);
1475 Concrete::Length x2
= dx
* Implementation::svg_path_strtod( & src
);
1476 Concrete::Length y2
= - dy
* Implementation::svg_path_strtod( & src
);
1477 Concrete::Length x3
= dx
* Implementation::svg_path_strtod( & src
);
1478 Concrete::Length y3
= - dy
* Implementation::svg_path_strtod( & src
);
1479 last
->front_
= new Concrete::Coords2D( 2 * *(last
->mid_
) - *(last
->rear_
) );
1480 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x3
, y3
) );
1481 last
->rear_
= new Concrete::Coords2D( x2
, y2
);
1482 elemPath
->push_back( last
);
1487 Concrete::Length x2
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1488 Concrete::Length y2
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1489 Concrete::Length x3
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1490 Concrete::Length y3
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1491 last
->front_
= new Concrete::Coords2D( 2 * *(last
->mid_
) - *(last
->rear_
) );
1492 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x3
, y3
) );
1493 last
->rear_
= new Concrete::Coords2D( x2
, y2
);
1494 elemPath
->push_back( last
);
1498 throw Exceptions::CoreOutOfRange( id_
, args
, 0, "Malformed SVG path string (failed to initialize command character)." );
1501 throw Exceptions::InternalError( "While reading SVG path string: Command character out of range." );
1506 catch( const std::string
& badNumber
)
1508 throw Exceptions::CoreOutOfRange( id_
, args
, 0, strrefdup( std::string( "Ill-formed number: " ) + badNumber
) );
1511 if( elemPath
!= NullPtr
< Lang::ElementaryPath2D
>( ) && ( singletons
|| elemPath
->duration( ) >= 1 ) )
1513 multiPath
->push_back( RefCountPtr
< const Lang::Path2D
>( elemPath
) );
1516 if( multiPath
->size( ) == 0 )
1518 throw Exceptions::CoreOutOfRange( id_
, args
, 0, "No path was produced." );
1520 if( multiPath
->size( ) == 1 )
1522 Kernel::ContRef cont
= evalState
->cont_
;
1523 if( multi
!= NullPtr
< FlagType
>( ) && multi
->val_
)
1525 cont
->takeValue( Kernel::ValueRef( multiPath
),
1530 cont
->takeValue( Kernel::ValueRef( multiPath
->front( ) ),
1536 if( multi
!= NullPtr
< FlagType
>( ) && ! multi
->val_
)
1538 throw Exceptions::CoreOutOfRange( id_
, args
, 0, "More than one sub-path conflicts with false for <multi>." );
1540 Kernel::ContRef cont
= evalState
->cont_
;
1541 cont
->takeValue( Kernel::ValueRef( multiPath
),
1547 class Core_sprintf
: public Lang::CoreFunction
1550 Core_sprintf( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
1552 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1556 throw Exceptions::CoreArityMismatch( id_
, 1, args
.size( ) );
1559 typedef const Lang::String Arg1Type
;
1560 RefCountPtr
< Arg1Type
> arg1
= Helpers::down_cast_CoreArgument
< Arg1Type
>( id_
, args
, i
, callLoc
);
1562 /* snprintf( 0, 0, ... ) does not seem to work properly on some systems.
1563 * Therefore, I resort to the use of a dummy string, and "n = 1".
1568 switch( args
.size( ) )
1572 size_t sz
= snprintf( dummy
, 1, arg1
->val_
.getPtr( ), 0 ); /* The final 0 is just a dummy argument that makes the compiler relax. */
1573 res
= new char[ sz
+ 1 ];
1574 status
= sprintf( res
, arg1
->val_
.getPtr( ), 0 ); /* The final 0 is just a dummy argument that makes the compiler relax. */
1581 typedef const Lang::String Arg2Type
;
1582 Arg2Type
* arg2
= dynamic_cast< Arg2Type
* >( args
.getValue( i
).getPtr( ) );
1585 size_t sz
= snprintf( dummy
, 1, arg1
->val_
.getPtr( ), arg2
->val_
.getPtr( ) );
1586 res
= new char[ sz
+ 1 ];
1587 status
= sprintf( res
, arg1
->val_
.getPtr( ), arg2
->val_
.getPtr( ) );
1592 typedef const Lang::Float Arg2Type
;
1593 Arg2Type
* arg2
= dynamic_cast< Arg2Type
* >( args
.getValue( i
).getPtr( ) );
1596 size_t sz
= snprintf( dummy
, 1, arg1
->val_
.getPtr( ), arg2
->val_
);
1597 res
= new char[ sz
+ 1 ];
1598 status
= sprintf( res
, arg1
->val_
.getPtr( ), arg2
->val_
);
1603 typedef const Lang::Integer Arg2Type
;
1604 Arg2Type
* arg2
= dynamic_cast< Arg2Type
* >( args
.getValue( i
).getPtr( ) );
1607 size_t sz
= snprintf( dummy
, 1, arg1
->val_
.getPtr( ), arg2
->val_
);
1608 res
= new char[ sz
+ 1 ];
1609 status
= sprintf( res
, arg1
->val_
.getPtr( ), arg2
->val_
);
1614 typedef const Lang::ChronologicalTime Arg2Type
;
1615 Arg2Type
* arg2
= dynamic_cast< Arg2Type
* >( args
.getValue( i
).getPtr( ) );
1618 const char * fmt
= arg1
->val_
.getPtr( );
1619 const struct tm
* tmp
= arg2
->temporary_localtime( );
1620 size_t sz
= strlen( fmt
) * 2;
1621 res
= new char[ sz
];
1622 while( strftime( res
, sz
, fmt
, tmp
) == 0 )
1626 res
= new char[ sz
];
1628 status
= 0; // Here, I'd like to check some error condition instead...
1632 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, i
, Interaction::SEVERAL_TYPES
);
1636 throw Exceptions::CoreOutOfRange( id_
, args
, 0, "The number of arguments is out of the implemented range." );
1641 throw Exceptions::InternalError( "Failed to assign to res in sprintf." );
1646 std::ostringstream oss
;
1647 oss
<< "Call to library routine returned negative value indicating an error: " << status
<< ".";
1648 throw Exceptions::CoreOutOfRange( id_
, args
, 0, strrefdup( oss
) );
1651 Kernel::ContRef cont
= evalState
->cont_
;
1652 cont
->takeValue( Kernel::ValueRef( new Lang::String( res
, false ) ),
1657 class Core_strftime
: public Lang::CoreFunction
1660 Core_strftime( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
1662 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1664 const size_t ARITY
= 0;
1665 CHECK_ARITY( args
, ARITY
, id_
);
1670 timeInfo
= localtime( & t
);
1671 std::ostringstream res
;
1672 res
<< timeInfo
->tm_hour
<< ":" << timeInfo
->tm_min
<< ":" << timeInfo
->tm_sec
;
1674 Kernel::ContRef cont
= evalState
->cont_
;
1675 cont
->takeValue( Kernel::ValueRef( new Lang::String( strrefdup( res
) ) ),
1680 class Core_ambient_light
: public Lang::CoreFunction
1683 Core_ambient_light( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
1684 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
1686 formals_
->appendEvaluatedCoreFormal( "color", Kernel::THE_SLOT_VARIABLE
);
1689 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1691 args
.applyDefaults( callLoc
);
1694 typedef const Lang::Gray ArgType
;
1695 ArgType
* col
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
1698 Kernel::ContRef cont
= evalState
->cont_
;
1699 cont
->takeValue( Kernel::ValueRef( new Lang::AmbientLightGray( col
->components( ) ) ),
1706 typedef const Lang::RGB ArgType
;
1707 ArgType
* col
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
1710 Kernel::ContRef cont
= evalState
->cont_
;
1711 cont
->takeValue( Kernel::ValueRef( new Lang::AmbientLightRGB( col
->components( ) ) ),
1717 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, 0, Helpers::typeSetString( Lang::Gray::staticTypeName( ), Lang::RGB::staticTypeName( ) ) );
1721 class Core_specular_light
: public Lang::CoreFunction
1724 Core_specular_light( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
1725 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
1727 formals_
->appendEvaluatedCoreFormal( "color", Kernel::THE_SLOT_VARIABLE
);
1728 formals_
->appendEvaluatedCoreFormal( "radius", Helpers::newValHandle( new Lang::Length( HUGE_VAL
) ) );
1729 formals_
->appendEvaluatedCoreFormal( "shadows", Kernel::THE_FALSE_VARIABLE
);
1732 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1734 args
.applyDefaults( callLoc
);
1736 typedef const Lang::Length RadiusType
;
1737 RefCountPtr
< RadiusType
> radius
= Helpers::down_cast_CoreArgument
< RadiusType
>( id_
, args
, 1, callLoc
);
1738 typedef const Lang::Boolean ShadowsType
;
1739 RefCountPtr
< ShadowsType
> shadows
= Helpers::down_cast_CoreArgument
< ShadowsType
>( id_
, args
, 2, callLoc
);
1742 typedef const Lang::Gray ArgType
;
1743 ArgType
* col
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
1746 Kernel::ContRef cont
= evalState
->cont_
;
1747 cont
->takeValue( Kernel::ValueRef( new Lang::SpecularLightGray( Concrete::Coords3D( 0, 0, 0 ),
1757 typedef const Lang::RGB ArgType
;
1758 ArgType
* col
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
1761 Kernel::ContRef cont
= evalState
->cont_
;
1762 cont
->takeValue( Kernel::ValueRef( new Lang::SpecularLightRGB( Concrete::Coords3D( 0, 0, 0 ),
1771 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, 0, Helpers::typeSetString( Lang::Gray::staticTypeName( ), Lang::RGB::staticTypeName( ) ) );
1775 class Core_distant_light
: public Lang::CoreFunction
1778 Core_distant_light( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
1779 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
1781 formals_
->appendEvaluatedCoreFormal( "color", Kernel::THE_SLOT_VARIABLE
);
1782 formals_
->appendEvaluatedCoreFormal( "shadows", Kernel::THE_FALSE_VARIABLE
);
1785 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1787 args
.applyDefaults( callLoc
);
1789 typedef const Lang::Boolean ShadowsType
;
1790 RefCountPtr
< ShadowsType
> shadows
= Helpers::down_cast_CoreArgument
< ShadowsType
>( id_
, args
, 1, callLoc
);
1793 typedef const Lang::Gray ArgType
;
1794 ArgType
* col
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
1797 Kernel::ContRef cont
= evalState
->cont_
;
1798 cont
->takeValue( Kernel::ValueRef( new Lang::DistantLightGray( Concrete::UnitFloatTriple( 0., 0., -1. ),
1807 typedef const Lang::RGB ArgType
;
1808 ArgType
* col
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
1811 Kernel::ContRef cont
= evalState
->cont_
;
1812 cont
->takeValue( Kernel::ValueRef( new Lang::DistantLightRGB( Concrete::UnitFloatTriple( 0., 0., -1. ),
1820 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, 0, Helpers::typeSetString( Lang::Gray::staticTypeName( ), Lang::RGB::staticTypeName( ) ) );
1824 class Core_textrenderingmode
: public Lang::CoreFunction
1827 Core_textrenderingmode( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
1828 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
1830 formals_
->appendEvaluatedCoreFormal( "fill", Kernel::THE_FALSE_VARIABLE
);
1831 formals_
->appendEvaluatedCoreFormal( "stroke", Kernel::THE_FALSE_VARIABLE
);
1834 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1836 args
.applyDefaults( callLoc
);
1838 typedef const Lang::Boolean FlagType
;
1839 RefCountPtr
< FlagType
> fill
= Helpers::down_cast_CoreArgument
< FlagType
>( id_
, args
, 0, callLoc
);
1840 RefCountPtr
< FlagType
> stroke
= Helpers::down_cast_CoreArgument
< FlagType
>( id_
, args
, 1, callLoc
);
1842 Kernel::ContRef cont
= evalState
->cont_
;
1843 cont
->takeValue( Kernel::ValueRef( new Lang::TextRenderingMode( fill
->val_
, stroke
->val_
, false ) ),
1848 class Core_manualkern
: public Lang::CoreFunction
1851 Core_manualkern( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
1853 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1855 // 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
1856 // the result is not used.
1857 RefCountPtr
< Lang::KernedText
> res( new Lang::KernedText( evalState
->dyn_
->getTextState( ), evalState
->dyn_
->getGraphicsState( ) ) );
1859 for( size_t i
= 0; i
!= args
.size( ); ++i
)
1863 typedef const Lang::String ArgType
;
1864 res
->pushString( Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( i
) ) );
1867 catch( const NonLocalExit::NotThisType
& ball
)
1869 /* Never mind, see below. */
1874 typedef const Lang::Float ArgType
;
1875 res
->pushKerning( Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( i
) )->val_
);
1878 catch( const NonLocalExit::NotThisType
& ball
)
1880 /* Never mind, see below. */
1885 typedef const Lang::KernedText ArgType
;
1886 Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( i
) )->push( res
.getPtr( ) );
1889 catch( const NonLocalExit::NotThisType
& ball
)
1891 /* Never mind, see below. */
1894 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, i
, Helpers::typeSetString( Lang::String::staticTypeName( ), Lang::Float::staticTypeName( ), Lang::KernedText::staticTypeName( ) ) );
1897 Kernel::ContRef cont
= evalState
->cont_
;
1898 cont
->takeValue( res
,
1903 class Core_automatickern
: public Lang::CoreFunction
1906 Core_automatickern( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
1908 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1910 iconv_t converter
= Helpers::requireUTF8ToUCS4Converter( );
1911 iconv_t backconverter
= Helpers::requireUCS4ToUTF8Converter( );
1913 RefCountPtr
< const FontMetrics::FontMetric
> metrics
= evalState
->dyn_
->getTextState( )->font_
->metrics( );
1914 if( metrics
->horizontalMetrics_
== NullPtr
< FontMetrics::WritingDirectionMetrics
>( ) )
1916 throw Exceptions::FontMetricsError( evalState
->dyn_
->getTextState( )->font_
->fontName( ), strrefdup( "No horizontal metrics defined." ) );
1919 // 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
1920 // the result is not used.
1921 RefCountPtr
< Lang::KernedText
> res( new Lang::KernedText( evalState
->dyn_
->getTextState( ), evalState
->dyn_
->getGraphicsState( ) ) );
1923 std::ostringstream pendingChars
;
1924 Kernel::UnicodeCodePoint
prevChar( 0 );
1925 double pendingKerning
= 0;
1927 const size_t backbufSize
= 5;
1928 char backbuf
[ backbufSize
];
1930 for( size_t i
= 0; i
!= args
.size( ); ++i
)
1934 typedef const Lang::String ArgType
;
1935 RefCountPtr
< ArgType
> str
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( i
) );
1937 const char * inbuf
= str
->val_
.getPtr( );
1938 size_t inbytesleft
= strlen( inbuf
);
1940 size_t bufSize
= 4 * inbytesleft
;
1941 char * buf
= new char[ bufSize
];
1942 DeleteOnExit
< char > bufDeleter( buf
);
1944 char * outbuf
= buf
;
1945 size_t outbytesleft
= bufSize
;
1946 // The ICONV_CAST macro is defined in config.h.
1947 size_t count
= iconv( converter
,
1948 ICONV_CAST( & inbuf
), & inbytesleft
,
1949 & outbuf
, & outbytesleft
);
1950 if( count
== (size_t)(-1) )
1952 if( errno
== EILSEQ
)
1954 throw Exceptions::MiscellaneousRequirement( "It is suspected that one of the UFT-8 characters used in showed text has no UCS-4 representation." );
1956 else if( errno
== EINVAL
)
1958 throw Exceptions::MiscellaneousRequirement( "It is suspected that showed text ended with an incomplete multibyte character." );
1960 else if( errno
== E2BIG
)
1962 throw Exceptions::InternalError( "Core_automatickern: The buffer allocated for UTF-8 to UCS-4 conversion was too small." );
1966 std::ostringstream msg
;
1967 msg
<< "iconv failed with an unrecognized error code: " << errno
;
1968 throw Exceptions::InternalError( strrefdup( msg
) );
1971 for( const char * src
= buf
; src
!= outbuf
; src
+= 4 )
1973 Kernel::UnicodeCodePoint currentChar
;
1974 currentChar
.decode_UCS4( src
);
1975 double currentKerning
= pendingKerning
- metrics
->getHorizontalKernPairXByCode( prevChar
, currentChar
);
1976 prevChar
= currentChar
;
1978 if( currentKerning
!= 0 )
1980 if( ! pendingChars
.str( ).empty( ) )
1982 res
->pushString( RefCountPtr
< const Lang::String
>( new Lang::String( strrefdup( pendingChars
) ) ) );
1983 pendingChars
.str( "" );
1985 res
->pushKerning( currentKerning
);
1988 // Copy the current (multibyte) character to the character queue
1990 const char * inbuf
= src
;
1991 char * outbuf
= backbuf
;
1992 size_t inbytesleft
= 4;
1993 size_t outbytesleft
= backbufSize
;
1994 // The ICONV_CAST macro is defined in config.h.
1995 size_t count
= iconv( backconverter
,
1996 ICONV_CAST( & inbuf
), & inbytesleft
,
1997 & outbuf
, & outbytesleft
);
1998 if( count
== (size_t)(-1) )
2000 if( errno
== EILSEQ
)
2002 throw Exceptions::ExternalError( "A character converted from UTF-8 could not be converted back to UFT-8." );
2004 else if( errno
== EINVAL
)
2006 throw Exceptions::ExternalError( "A character converted from UTF-8 was deemed incomplete." );
2008 else if( errno
== E2BIG
)
2010 throw Exceptions::InternalError( "The buffer allocated for conversion of a single character back to UTF-8 was too small." );
2014 std::ostringstream msg
;
2015 msg
<< "iconv failed with an unrecognized error code: " << errno
;
2016 throw Exceptions::InternalError( strrefdup( msg
) );
2020 pendingChars
<< backbuf
;
2025 catch( const NonLocalExit::NotThisType
& ball
)
2027 /* Never mind, see below. */
2032 typedef const Lang::Float ArgType
;
2033 pendingKerning
+= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( i
) )->val_
;
2036 catch( const NonLocalExit::NotThisType
& ball
)
2038 /* Never mind, see below. */
2041 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, i
, Helpers::typeSetString( Lang::String::staticTypeName( ), Lang::Float::staticTypeName( ) ) );
2044 if( ! pendingChars
.str( ).empty( ) )
2046 res
->pushString( RefCountPtr
< const Lang::String
>( new Lang::String( strrefdup( pendingChars
) ) ) );
2047 pendingChars
.str( "" );
2050 Kernel::ContRef cont
= evalState
->cont_
;
2051 cont
->takeValue( res
,
2056 class Core_newrandom
: public Lang::CoreFunction
2059 Core_newrandom( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
2060 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
2062 formals_
->appendEvaluatedCoreFormal( "seed", Kernel::THE_SLOT_VARIABLE
);
2063 formals_
->appendEvaluatedCoreFormal( "size", Helpers::newValHandle( new Lang::Integer( 32 ) ) );
2066 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2068 args
.applyDefaults( callLoc
);
2070 typedef const Lang::Integer SizeType
;
2071 Lang::Integer::ValueType sz
= Helpers::down_cast_CoreArgument
< SizeType
>( id_
, args
, 1, callLoc
)->val_
;
2074 throw Exceptions::CoreOutOfRange( id_
, args
, 1, "The size must be at least 8." );
2078 throw Exceptions::CoreOutOfRange( id_
, args
, 1, "The size must at most 256." );
2085 typedef const Lang::ChronologicalTime SeedType
;
2087 RefCountPtr
< SeedType
> seed
= Helpers::try_cast_CoreArgument
< SeedType
>( args
.getValue( argsi
) );
2089 Kernel::ContRef cont
= evalState
->cont_
;
2090 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::HotRandomSeed( sz
, seed
->val( ) ) ),
2094 catch( const NonLocalExit::NotThisType
& ball
)
2096 /* Never mind, see below. */
2101 typedef const Lang::Integer SeedType
;
2103 RefCountPtr
< SeedType
> seed
= Helpers::try_cast_CoreArgument
< SeedType
>( args
.getValue( argsi
) );
2105 Kernel::ContRef cont
= evalState
->cont_
;
2106 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::HotRandomSeed( sz
, seed
->val_
) ),
2110 catch( const NonLocalExit::NotThisType
& ball
)
2112 /* Never mind, see below. */
2115 throw Exceptions::CoreTypeMismatch( callLoc
, id_
, args
, argsi
, Helpers::typeSetString( Lang::Integer::staticTypeName( ), Lang::ChronologicalTime::staticTypeName( ) ) );
2119 class Core_devrandom
: public Lang::CoreFunction
2122 Core_devrandom( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
2123 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
2125 formals_
->appendCoreStateFormal( "device" );
2126 formals_
->appendEvaluatedCoreFormal( "size", Helpers::newValHandle( new Lang::Integer( 32 ) ) );
2129 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2131 args
.applyDefaults( callLoc
);
2133 typedef const Lang::Integer SizeType
;
2134 Lang::Integer::ValueType sz
= Helpers::down_cast_CoreArgument
< SizeType
>( id_
, args
, 0, callLoc
)->val_
;
2137 throw Exceptions::CoreOutOfRange( id_
, args
, 0, "The size must be at least 8." );
2141 throw Exceptions::CoreOutOfRange( id_
, args
, 0, "The size must at most 256." );
2144 typedef Kernel::WarmRandomDevice GeneratorType
;
2145 GeneratorType
* gen
= Helpers::down_cast_CoreState
< GeneratorType
>( id_
, args
, 0, callLoc
);
2147 Kernel::ContRef cont
= evalState
->cont_
;
2148 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::HotRandomSeed( static_cast< size_t >( sz
), gen
) ),
2153 class Core_destination
: public Lang::CoreFunction
2156 Core_destination( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
2157 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
2159 formals_
->appendEvaluatedCoreFormal( "remote", Kernel::THE_FALSE_VARIABLE
);
2160 formals_
->appendEvaluatedCoreFormal( "name", Kernel::THE_VOID_VARIABLE
);
2161 formals_
->appendEvaluatedCoreFormal( "level", Kernel::THE_VOID_VARIABLE
);
2162 formals_
->appendEvaluatedCoreFormal( "text", Kernel::THE_VOID_VARIABLE
);
2163 formals_
->appendEvaluatedCoreFormal( "open", Kernel::THE_FALSE_VARIABLE
);
2164 formals_
->appendEvaluatedCoreFormal( "bold", Kernel::THE_FALSE_VARIABLE
);
2165 formals_
->appendEvaluatedCoreFormal( "italic", Kernel::THE_FALSE_VARIABLE
);
2166 formals_
->appendEvaluatedCoreFormal( "color", Helpers::newValHandle( new Lang::RGB( Concrete::RGB( 0, 0, 0 ) ) ) );
2167 formals_
->appendEvaluatedCoreFormal( "sides", Kernel::THE_VOID_VARIABLE
);
2168 formals_
->appendEvaluatedCoreFormal( "target", Kernel::THE_VOID_VARIABLE
);
2169 formals_
->appendEvaluatedCoreFormal( "fittobbox", Kernel::THE_VOID_VARIABLE
);
2170 formals_
->appendEvaluatedCoreFormal( "zoom", Kernel::THE_VOID_VARIABLE
);
2171 formals_
->appendEvaluatedCoreFormal( "transform", Kernel::THE_TRUE_VARIABLE
);
2174 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2176 args
.applyDefaults( callLoc
);
2179 const size_t remove_i
= argsi
;
2180 typedef const Lang::Boolean RemoteType
;
2181 bool remote
= Helpers::down_cast_CoreArgument
< RemoteType
>( id_
, args
, argsi
, callLoc
)->val_
;
2184 typedef const Lang::String NameType
;
2185 RefCountPtr
< NameType
> nameVal
= Helpers::down_cast_CoreArgument
< NameType
>( id_
, args
, argsi
, callLoc
, true );
2186 RefCountPtr
< const char > name
= RefCountPtr
< const char >( NullPtr
< const char >( ) );
2187 if( nameVal
!= NullPtr
< NameType
>( ) )
2189 const SimplePDF::PDF_Version::Version STRINGDESTS_VERSION
= SimplePDF::PDF_Version::PDF_1_2
;
2190 if( Kernel::the_PDF_version
.greaterOrEqual( STRINGDESTS_VERSION
) )
2192 name
= nameVal
->val_
;
2196 Kernel::the_PDF_version
.message( STRINGDESTS_VERSION
, "The naming of a destination was ignored." );
2197 // Note that this will leave name being null, and hence generate further errors if remote_.
2200 if( nameVal
== NullPtr
< NameType
>( ) ) // Note why this is not an else clause!
2204 throw Exceptions::CoreOutOfRange( id_
, args
, remove_i
, "The destination cannot be remote if no name is given." );
2209 const size_t outlineLevel_i
= argsi
;
2210 typedef const Lang::Integer OutlineLevelType
;
2211 RefCountPtr
< OutlineLevelType
> levelVal
= Helpers::down_cast_CoreArgument
< OutlineLevelType
>( id_
, args
, argsi
, callLoc
, true );
2212 int outlineLevel
= -1; // This will remain negative only if the level is not present.
2213 if( levelVal
!= NullPtr
< OutlineLevelType
>( ) )
2215 outlineLevel
= levelVal
->val_
;
2216 if( outlineLevel
< 0 )
2218 throw Exceptions::CoreOutOfRange( id_
, args
, argsi
, "The outline level must be non-negative." );
2223 typedef const Lang::String OutlineTextType
;
2224 RefCountPtr
< OutlineTextType
> textVal
= Helpers::down_cast_CoreArgument
< OutlineTextType
>( id_
, args
, argsi
, callLoc
, true );
2225 RefCountPtr
< const char > outlineText
= RefCountPtr
< const char >( NullPtr
< const char >( ) );
2226 if( textVal
!= NullPtr
< OutlineTextType
>( ) )
2228 outlineText
= textVal
->val_
;
2232 if( outlineLevel
>= 0 )
2234 throw Exceptions::CoreOutOfRange( id_
, args
, outlineLevel_i
, "Without an outline text, it is not allowed to make an outline item." );
2239 typedef const Lang::Boolean OutlineOpenType
;
2240 bool outlineOpen
= Helpers::down_cast_CoreArgument
< OutlineOpenType
>( id_
, args
, argsi
, callLoc
)->val_
;
2243 typedef const Lang::Boolean OutlineBoldType
;
2244 bool outlineBold
= Helpers::down_cast_CoreArgument
< OutlineBoldType
>( id_
, args
, argsi
, callLoc
)->val_
;
2247 typedef const Lang::Boolean OutlineItalicType
;
2248 bool outlineItalic
= Helpers::down_cast_CoreArgument
< OutlineItalicType
>( id_
, args
, argsi
, callLoc
)->val_
;
2251 typedef const Lang::RGB OutlineColorType
;
2252 Concrete::RGB outlineColor
= Helpers::down_cast_CoreArgument
< OutlineColorType
>( id_
, args
, argsi
, callLoc
)->components( );
2255 const size_t sidesMode_i
= argsi
;
2256 typedef const Lang::Symbol SidesModeType
;
2257 RefCountPtr
< SidesModeType
> sidesVal
= Helpers::down_cast_CoreArgument
< SidesModeType
>( id_
, args
, argsi
, callLoc
, true );
2260 const size_t target_i
= argsi
;
2261 typedef const Lang::Drawable2D TargetType
;
2262 RefCountPtr
< TargetType
> target
= Helpers::down_cast_CoreArgument
< TargetType
>( id_
, args
, argsi
, callLoc
, true );
2264 Lang::DocumentDestination::Sides sides
= Lang::DocumentDestination::PAGE
; // Defaults to false, unless a target is given.
2265 if( target
!= NullPtr
< TargetType
>( ) )
2267 sides
= Lang::DocumentDestination::TOPLEFT
;
2270 throw Exceptions::CoreOutOfRange( id_
, args
, target_i
, "The target can not be specified for remote destinations." );
2273 static Lang::Symbol
SIDES_TopLeft( "topleft" );
2274 static Lang::Symbol
SIDES_Page( "page" );
2275 static Lang::Symbol
SIDES_Top( "top" );
2276 static Lang::Symbol
SIDES_Left( "left" );
2277 static Lang::Symbol
SIDES_Rectangle( "rectangle" );
2278 if( sidesVal
!= NullPtr
< SidesModeType
>( ) )
2280 if( *sidesVal
== SIDES_TopLeft
)
2282 sides
= Lang::DocumentDestination::TOPLEFT
;
2284 else if( *sidesVal
== SIDES_Page
)
2286 if( target
!= NullPtr
< TargetType
>( ) )
2288 throw Exceptions::CoreOutOfRange( id_
, args
, sidesMode_i
, "The sides mode cannot be page when a target object is present." );
2290 sides
= Lang::DocumentDestination::PAGE
;
2292 else if( *sidesVal
== SIDES_Top
)
2294 sides
= Lang::DocumentDestination::TOP
;
2296 else if( *sidesVal
== SIDES_Left
)
2298 sides
= Lang::DocumentDestination::LEFT
;
2300 else if( *sidesVal
== SIDES_Rectangle
)
2302 sides
= Lang::DocumentDestination::RECTANGLE
;
2306 std::ostringstream oss
;
2307 oss
<< "Valid sides modes are the symbols { "
2308 << SIDES_TopLeft
.name( ).getPtr( ) << ", "
2309 << SIDES_Page
.name( ).getPtr( ) << ", "
2310 << SIDES_Top
.name( ).getPtr( ) << ", "
2311 << SIDES_Left
.name( ).getPtr( ) << ", "
2312 << SIDES_Rectangle
.name( ).getPtr( )
2314 throw Exceptions::CoreOutOfRange( id_
, args
, sidesMode_i
, strrefdup( oss
) );
2319 typedef const Lang::Boolean FitToType
;
2320 RefCountPtr
< FitToType
> fittobboxVal
= Helpers::down_cast_CoreArgument
< FitToType
>( id_
, args
, argsi
, callLoc
, true );
2321 bool fittobbox
= false;
2322 if( fittobboxVal
!= NullPtr
< FitToType
>( ) )
2324 if( remote
|| sides
== Lang::DocumentDestination::TOPLEFT
|| sides
== Lang::DocumentDestination::RECTANGLE
)
2326 throw Exceptions::CoreOutOfRange( id_
, args
, argsi
, "The fit-to-bbox flag cannot be specified in this mode." );
2328 fittobbox
= fittobboxVal
->val_
;
2332 typedef const Lang::Float ZoomType
;
2333 RefCountPtr
< ZoomType
> zoomVal
= Helpers::down_cast_CoreArgument
< ZoomType
>( id_
, args
, argsi
, callLoc
, true );
2334 double zoom
= 0; // This will remain zero only if the zoom argument is not specified.
2335 if( zoomVal
!= NullPtr
< ZoomType
>( ) )
2337 if( remote
|| sides
!= Lang::DocumentDestination::TOPLEFT
)
2339 throw Exceptions::CoreOutOfRange( id_
, args
, argsi
, "The zoom can only be specified when using the top-left sides." );
2341 zoom
= zoomVal
->val_
;
2344 throw Exceptions::CoreOutOfRange( id_
, args
, argsi
, "The zoom value must be positive." );
2349 typedef const Lang::Boolean DoTransformType
;
2350 bool doTransform
= Helpers::down_cast_CoreArgument
< DoTransformType
>( id_
, args
, argsi
, callLoc
)->val_
;
2352 Kernel::ContRef cont
= evalState
->cont_
;
2355 RefCountPtr
< const Lang::DocumentDestination
>
2356 taggedObj( new Lang::DocumentDestination( remote
, name
, outlineLevel
,
2357 outlineText
, outlineOpen
, outlineBold
, outlineItalic
, outlineColor
) );
2358 cont
->takeValue( RefCountPtr
< const Lang::Value
>
2359 ( new Lang::TaggedValue2D( Kernel::THE_NAVIGATION_SYMBOL
, taggedObj
) ),
2364 RefCountPtr
< const Lang::DocumentDestination
>
2365 taggedObj( new Lang::DocumentDestination( name
, outlineLevel
,
2366 outlineText
, outlineOpen
, outlineBold
, outlineItalic
, outlineColor
,
2367 sides
, target
, fittobbox
, zoom
) );
2370 cont
->takeValue( RefCountPtr
< const Lang::Value
>
2371 ( new Lang::TaggedGeometric2D( Kernel::THE_NAVIGATION_SYMBOL
, taggedObj
) ),
2376 cont
->takeValue( RefCountPtr
< const Lang::Value
>
2377 ( new Lang::TaggedValue2D( Kernel::THE_NAVIGATION_SYMBOL
, taggedObj
) ),
2384 class Core_importFont
: public Lang::CoreFunction
2390 RefCountPtr
< const char > filename_
;
2391 CacheKey( bool outline
, const RefCountPtr
< const char > & filename
)
2392 : outline_( outline
), filename_( filename
)
2396 bool operator < ( const CacheKey
& other
) const
2398 if( ! outline_
&& other
.outline_
)
2402 if( outline_
&& ! other
.outline_
)
2406 return strcmp( filename_
.getPtr( ), other
.filename_
.getPtr( ) ) < 0;
2410 static std::map
< CacheKey
, RefCountPtr
< const Lang::Value
> > cache
;
2412 Core_importFont( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
2413 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
2415 formals_
->appendEvaluatedCoreFormal( "family", Kernel::THE_SLOT_VARIABLE
);
2416 formals_
->appendEvaluatedCoreFormal( "style", Kernel::THE_VOID_VARIABLE
);
2417 formals_
->appendEvaluatedCoreFormal( "outline", Kernel::THE_FALSE_VARIABLE
);
2420 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2423 throw Exceptions::BuildRequirement( Interaction::BUILD_REQ_FREETYPE
, id_
, callLoc
);
2425 args
.applyDefaults( callLoc
);
2428 std::string full_filename
;
2429 #ifndef HAVE_FONTCONFIG
2430 /* Here, it would be possible to allow the user to point out the font file directly instead of using FontConfig,
2431 * but currently there is no such option.
2433 throw Exceptions::BuildRequirement( Interaction::BUILD_REQ_FONTCONFIG
, id_
, callLoc
);
2435 FcPattern
* pat
= FcPatternCreate( );
2436 Helpers::AutoDestroyFcPattern
destroy_pat( pat
);
2438 FcValue fc_fontformat
;
2439 fc_fontformat
.type
= FcTypeString
;
2440 fc_fontformat
.u
.s
= reinterpret_cast< const FcChar8
* >( "TrueType" );
2441 FcPatternAdd( pat
, "fontformat", fc_fontformat
, FcFalse
);
2443 size_t argsi_family
= argsi
;
2444 typedef const Lang::String ArgType
;
2445 RefCountPtr
< ArgType
> family
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, argsi_family
, callLoc
);
2447 fc_family
.type
= FcTypeString
;
2448 fc_family
.u
.s
= reinterpret_cast< const FcChar8
* >( family
->val_
.getPtr( ) );
2449 FcPatternAdd( pat
, "family", fc_family
, FcFalse
);
2452 size_t argsi_style
= argsi
;
2453 RefCountPtr
< ArgType
> style
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, argsi_style
, callLoc
, true );
2455 if( style
!= NullPtr
< ArgType
>( ) )
2457 fc_style
.type
= FcTypeString
;
2458 fc_style
.u
.s
= reinterpret_cast< const FcChar8
* >( style
->val_
.getPtr( ) );
2459 FcPatternAdd( pat
, "style", fc_family
, FcFalse
);
2462 FcFontSet
* sysFonts
= FcConfigGetFonts( NULL
, FcSetSystem
);
2466 FcDefaultSubstitute( pat
);
2467 FcConfigSubstitute( NULL
, pat
, FcMatchPattern
); /* Not sure if FcMatchPattern is the correct value to pass here. There are two more possible values, and no documentation. See fontconfig/fontconfig.h. */
2468 FcPattern
* match_res
= FcFontSetMatch( NULL
, & sysFonts
, 1, pat
, & fc_res
);
2469 if( match_res
== 0 )
2471 throw Exceptions::ExternalError( "FontConfig' FcFontSetMatch returned with failure." );
2473 Helpers::AutoDestroyFcPattern
destroy_match_res( match_res
);
2478 // OK, just continue;
2480 case FcResultNoMatch
:
2481 throw Exceptions::OutOfRange( callLoc
, "FontConfig returned no matching font." );
2482 case FcResultOutOfMemory
:
2483 throw Exceptions::ExternalError( "FontConfig got out of memory." );
2484 case FcResultTypeMismatch
:
2486 // std::ostringstream msg;
2487 // msg << "Unexpected FcResult from FcFontSetMatch: " << "FcResultTypeMismatch" << " (ignored)." ;
2488 // WARN_OR_THROW( Exceptions::InternalError( strrefdup( msg ), true ) );
2493 // std::ostringstream msg;
2494 // msg << "Unexpected FcResult from FcFontSetMatch: " << "FcResultNoId" << " (ignored)." ;
2495 // WARN_OR_THROW( Exceptions::InternalError( strrefdup( msg ), true ) );
2500 // std::ostringstream msg;
2501 // msg << "Unexpected FcResult from FcFontSetMatch: " << fc_res << " (ignored)." ;
2502 // WARN_OR_THROW( Exceptions::InternalError( strrefdup( msg ), true ) );
2504 // throw Exceptions::InternalError( "Unexpected FcResult from FcFontSetMatch." );
2507 // FcPatternPrint( match_res );
2509 FcChar8
* fc_tmp_string
;
2510 switch( FcPatternGetString( match_res
, "fontformat", 0, & fc_tmp_string
) )
2513 // OK, just continue;
2515 case FcResultNoMatch
:
2516 throw Exceptions::ExternalError( "FontConfig says that the font does not have a 'fontformat'." );
2517 case FcResultTypeMismatch
:
2518 throw Exceptions::ExternalError( "FontConfig says 'fontformat' has the wrong type." );
2520 throw Exceptions::ExternalError( "FontConfig says 'fontformat' is missing something." );
2521 case FcResultOutOfMemory
:
2522 throw Exceptions::ExternalError( "FontConfig got out of memory." );
2524 if( strcmp( reinterpret_cast< const char * >( fc_tmp_string
), "TrueType" ) != 0 ) // This is OK, since "TrueType" is in the ASCII range.
2526 throw Exceptions::OutOfRange( callLoc
, "Font file format not supported by Shapes, only TrueType is supported at the moment." );
2529 switch( FcPatternGetString( match_res
, "file", 0, & fc_tmp_string
) )
2532 // OK, just continue;
2534 case FcResultNoMatch
:
2535 throw Exceptions::ExternalError( "FontConfig says that the font does not have a 'file' (filename)." );
2536 case FcResultTypeMismatch
:
2537 throw Exceptions::ExternalError( "FontConfig says 'file' has the wrong type." );
2539 throw Exceptions::ExternalError( "FontConfig says 'file' is missing something." );
2540 case FcResultOutOfMemory
:
2541 throw Exceptions::ExternalError( "FontConfig got out of memory." );
2543 full_filename
= reinterpret_cast< const char * >( fc_tmp_string
); /* Let us hope that this string is in the ASCII range! */
2547 size_t argsi_outline
= argsi
;
2548 bool outline
= Helpers::down_cast_CoreArgument
< const Lang::Boolean
>( id_
, args
, argsi_outline
, callLoc
)->val_
;
2549 CacheKey
cacheKey( outline
, strrefdup( full_filename
.c_str( ) ) );
2551 typedef typeof cache MapType
;
2552 MapType::const_iterator i
= cache
.find( cacheKey
);
2553 if( i
!= cache
.end( ) )
2555 Kernel::ContRef cont
= evalState
->cont_
;
2556 cont
->takeValue( i
->second
,
2565 FT_Error error
= FT_New_Face( Kernel::theFreeType
,
2566 full_filename
.c_str( ),
2569 if( error
== FT_Err_Unknown_File_Format
)
2571 throw Exceptions::ExternalError( "Font file format not supported by FreeType." );
2573 else if( error
!= 0 )
2575 std::ostringstream msg
;
2576 msg
<< "FreeType failed to open " << full_filename
<< ", reason: " << Kernel::FreeTypeErrorMessage( error
) ;
2577 throw Exceptions::ExternalError( strrefdup( msg
) );
2580 const char * PostScriptName
= FT_Get_Postscript_Name( face
); /* See comment on the next line! */
2581 std::ostringstream baseFontName
; /* The PostScriptName pointer shall only be used as long as this object is in scope. */
2582 if( PostScriptName
== 0 )
2584 for( const char * src
= full_filename
.c_str( ); *src
!= '\0'; ++src
)
2592 baseFontName
<< *src
;
2595 PostScriptName
= baseFontName
.str( ).c_str( );
2598 if( ! FT_IS_SFNT( face
) )
2600 throw Exceptions::OutOfRange( callLoc
, "Font file format not supported by Shapes, only TrueType is supported at the moment." );
2605 FT_UShort fsType
= FT_Get_FSType_Flags( face
);
2606 if( ( fsType
& ( FT_FSTYPE_INSTALLABLE_EMBEDDING
|
2607 FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING
|
2608 FT_FSTYPE_EDITABLE_EMBEDDING
) )
2611 std::ostringstream msg
;
2612 msg
<< "The font " << PostScriptName
<< " does not permit embedding, and cannot be used with Shapes. Flags: " << std::hex
<< static_cast< int >( fsType
) << "." ;
2613 throw Exceptions::MiscellaneousRequirement( strrefdup( msg
) );
2616 throw Exceptions::MiscellaneousRequirement( strrefdup( "Shapes does not permit embedding of fonts, since your FreeType library is too old to provide licensing information about your fonts." ) );
2620 FontMetrics::FreeType2_Metric
* newMetrics
= new FontMetrics::FreeType2_Metric( face
);
2621 RefCountPtr
< const FontMetrics::FontMetric
> metrics
= RefCountPtr
< const FontMetrics::FontMetric
>( newMetrics
);
2623 RefCountPtr
< SimplePDF::PDF_Dictionary
> dic
;
2624 RefCountPtr
< SimplePDF::PDF_Object
> resource
= SimplePDF::indirect( dic
, & Kernel::theIndirectObjectCount
);
2625 (*dic
)[ "Type" ] = SimplePDF::newName( "Font" );
2626 (*dic
)[ "Subtype" ] = SimplePDF::newName( "Type0" );
2628 RefCountPtr
< SimplePDF::PDF_Dictionary
> descendant
;
2629 RefCountPtr
< SimplePDF::PDF_Vector
> descendants
;
2630 descendants
->vec
.push_back( descendant
);
2631 (*dic
)[ "DescendantFonts" ] = descendants
;
2633 RefCountPtr
< SimplePDF::PDF_ToUnicode::CharSet
> usedChars
;
2635 (*descendant
)[ "Type" ] = SimplePDF::newName( "Font" );
2636 (*descendant
)[ "Subtype" ] = SimplePDF::newName( "CIDFontType2" );
2638 RefCountPtr
< SimplePDF::PDF_Name
> fontName
= RefCountPtr
< SimplePDF::PDF_Name
>( new SimplePDF::PDF_Name( PostScriptName
) );
2639 (*dic
)[ "BaseFont" ] = fontName
;
2640 (*descendant
)[ "BaseFont" ] = fontName
;
2641 (*dic
)[ "Encoding" ] = SimplePDF::newName( "Identity-H" );
2642 (*descendant
)[ "BaseFont" ] = fontName
;
2644 RefCountPtr
< SimplePDF::PDF_Dictionary
> CIDSystemInfo
;
2645 (*CIDSystemInfo
)[ "Registry" ] = SimplePDF::newString( "Adobe" );
2646 (*CIDSystemInfo
)[ "Ordering" ] = SimplePDF::newString( "Identity" );
2647 (*CIDSystemInfo
)[ "Supplement" ] = SimplePDF::newString( "0" );
2648 (*descendant
)[ "CIDSystemInfo" ] = CIDSystemInfo
;
2649 (*descendant
)[ "CIDToGIDMap" ] = SimplePDF::newName( "Identity" );
2651 (*descendant
)[ "DW" ] = SimplePDF::newFloat( 0.7 * 1000 ); /* Default width. */
2653 RefCountPtr
< SimplePDF::PDF_Dictionary
> fontDescriptor
;
2654 (*fontDescriptor
)[ "Type" ] = SimplePDF::newName( "FontDescriptor" );
2655 (*fontDescriptor
)[ "FontName" ] = fontName
;
2656 (*fontDescriptor
)[ "Flags" ] = SimplePDF::newInt( (size_t)(1) << ( 6 - 1 ) ); // This is the "Nonsymbolic" flag, although we don't know if it really is a non-symbolic font...
2657 (*fontDescriptor
)[ "FontBBox" ] =
2658 RefCountPtr
< SimplePDF::PDF_Vector
>( new SimplePDF::PDF_Vector( newMetrics
->fontBBoxXMin_
* 1000, newMetrics
->fontBBoxYMin_
* 1000,
2659 newMetrics
->fontBBoxXMax_
* 1000, newMetrics
->fontBBoxYMax_
* 1000 ) );
2660 (*fontDescriptor
)[ "ItalicAngle" ] = SimplePDF::newFloat( 0 );
2661 (*fontDescriptor
)[ "Ascent" ] = SimplePDF::newFloat( 1 * 1000 );
2662 (*fontDescriptor
)[ "Descent" ] = SimplePDF::newFloat( -0.5 * 1000 );
2664 RefCountPtr
< SimplePDF::PDF_Stream_out
> fontFile
= RefCountPtr
< SimplePDF::PDF_Stream_out
>( new SimplePDF::PDF_Stream_out( ) );
2665 (*fontFile
)[ "Filter" ] = SimplePDF::newName( "FlateDecode" );
2666 std::ifstream
iFile( full_filename
.c_str( ) );
2667 if( ! iFile
.is_open( ) )
2669 throw Exceptions::FileReadOpenError( callLoc
, strrefdup( full_filename
), 0, 0 );
2672 iFile
.seekg( 0, std::ios::end
);
2673 std::streamoff tmp
= iFile
.tellg( );
2674 std::streamsize size
= tmp
- static_cast< std::streamoff
>( 0 );
2675 (*fontFile
)[ "Length1" ] = SimplePDF::newInt( size
);
2676 char * buf
= new char[ size
];
2677 iFile
.seekg( 0, std::ios::beg
);
2678 iFile
.read( buf
, size
);
2679 fontFile
->data
.write( buf
, size
);
2682 (*fontDescriptor
)[ "FontFile2" ] = SimplePDF::indirect( fontFile
, & Kernel::theIndirectObjectCount
);
2684 (*descendant
)[ "FontDescriptor" ] = fontDescriptor
;
2686 RefCountPtr
< const Lang::Font
> res
= RefCountPtr
< const Lang::Font
>( new Lang::FreeTypeFont( face
,
2687 newMetrics
->fontName_
,
2692 RefCountPtr
< SimplePDF::PDF_ToUnicode
> toUnicode( new SimplePDF::PDF_ToUnicode( usedChars
, res
) );
2693 (*dic
)[ "ToUnicode" ] = SimplePDF::indirect( toUnicode
, & Kernel::theIndirectObjectCount
);
2694 RefCountPtr
< SimplePDF::PDF_Widths
> widths( new SimplePDF::PDF_Widths( usedChars
, res
) );
2695 (*descendant
)[ "W" ] = SimplePDF::indirect( widths
, & Kernel::theIndirectObjectCount
);
2698 typedef typeof cache MapType
;
2699 cache
.insert( MapType::value_type( cacheKey
, res
) );
2701 Kernel::ContRef cont
= evalState
->cont_
;
2702 cont
->takeValue( res
,
2708 std::map
< Core_importFont::CacheKey
, RefCountPtr
< const Lang::Value
> > Core_importFont::cache
;
2710 class Core_Unicode
: public Lang::CoreFunction
2713 Core_Unicode( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
2714 : CoreFunction( ns
, name
)
2717 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2719 const size_t ARITY
= 1;
2720 CHECK_ARITY( args
, ARITY
, id_
);
2723 typedef const Lang::Integer ArgType
;
2724 ArgType::ValueType arg
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, argsi
, callLoc
)->val_
;
2727 throw Exceptions::CoreOutOfRange( id_
, args
, argsi
, "Unicode code points cannot be negative." );
2730 Kernel::ContRef cont
= evalState
->cont_
;
2731 cont
->takeValue( Kernel::ValueRef( new Lang::Character( arg
) ),
2736 class Core_AdobeGlyphList
: public Lang::CoreFunction
2739 Core_AdobeGlyphList( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
2740 : CoreFunction( ns
, name
)
2743 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2745 const size_t ARITY
= 1;
2746 CHECK_ARITY( args
, ARITY
, id_
);
2749 typedef const Lang::Symbol ArgType
;
2750 RefCountPtr
< ArgType
> arg
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, argsi
, callLoc
);
2751 if( arg
->isUnique( ) )
2753 throw Exceptions::CoreOutOfRange( id_
, args
, argsi
, "Unique symbols do not correspond to any glyphs." );
2755 FontMetrics::GlyphList::UnicodeType res
;
2756 const FontMetrics::GlyphList
& glyphList
= Helpers::requireGlyphList( );
2757 if( ! glyphList
.name_to_UCS4( arg
->name( ).getPtr( ), & res
) )
2759 std::ostringstream msg
;
2760 msg
<< "Unrecognized glyph name: " ;
2762 throw Exceptions::CoreOutOfRange( id_
, args
, argsi
, strrefdup( msg
) );
2764 Kernel::ContRef cont
= evalState
->cont_
;
2765 cont
->takeValue( Kernel::ValueRef( new Lang::Character( res
) ),
2774 Lang::Core_range::Core_range( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
2775 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
2777 formals_
->appendEvaluatedCoreFormal( "begin", Kernel::THE_VOID_VARIABLE
);
2778 formals_
->appendEvaluatedCoreFormal( "end", Kernel::THE_VOID_VARIABLE
);
2779 formals_
->appendEvaluatedCoreFormal( "step", Kernel::THE_VOID_VARIABLE
);
2780 formals_
->appendEvaluatedCoreFormal( "count", Kernel::THE_VOID_VARIABLE
);
2784 Lang::Core_range::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2786 RefCountPtr
< const Interaction::CoreLocation
> coreLoc( new Interaction::BoundLocation( id_
) );
2787 makeRange( coreLoc
, evalState
, args
, callLoc
);
2791 Lang::Core_range::makeRange( const RefCountPtr
< const Interaction::CoreLocation
> & coreLoc
, Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
, bool isSpan
, RefCountPtr
< const Lang::Value
> lastPtr
)
2793 const size_t argsi_begin
= 0;
2794 const size_t argsi_end
= 1;
2795 const size_t argsi_step
= 2;
2796 const size_t argsi_count
= 3;
2798 typedef const Lang::Integer CountType
;
2800 args
.applyDefaults( callLoc
);
2804 typedef const Lang::Integer ArgType
;
2806 RefCountPtr
< ArgType
> beginPtr
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi_begin
), true );
2807 RefCountPtr
< ArgType
> endPtr
= Helpers::down_cast_CoreArgument
< ArgType
>( coreLoc
, args
, argsi_end
, callLoc
, true );
2808 if( beginPtr
== NullPtr
< ArgType
>( ) && endPtr
== NullPtr
< ArgType
>( ) )
2810 throw Exceptions::CoreRequirement( "At least one of the arguments <begin> and <end> must be provided.", coreLoc
, callLoc
);
2812 RefCountPtr
< ArgType
> stepPtr
= Helpers::down_cast_CoreArgument
< ArgType
>( coreLoc
, args
, argsi_step
, callLoc
, true );
2813 RefCountPtr
< CountType
> countPtr
= Helpers::down_cast_CoreArgument
< CountType
>( coreLoc
, args
, argsi_count
, callLoc
, true );
2815 if( beginPtr
!= NullPtr
< ArgType
>( ) && endPtr
!= NullPtr
< ArgType
>( ) &&
2816 stepPtr
!= NullPtr
< ArgType
>( ) && countPtr
!= NullPtr
< CountType
>( ) )
2818 throw Exceptions::CoreRequirement( "At least one of the arguments must be omitted.", coreLoc
, callLoc
);
2821 ArgType::ValueType begin
= 0;
2822 ArgType::ValueType step
= 1;
2823 ArgType::ValueType last
= isSpan
? lastPtr
.down_cast
< ArgType
>( )->val_
: 0;
2826 if( stepPtr
!= NullPtr
< ArgType
>( ) )
2828 step
= stepPtr
->val_
;
2830 if( countPtr
!= NullPtr
< CountType
>( ) )
2832 if( countPtr
->val_
< 0 )
2834 throw Exceptions::CoreOutOfRange( coreLoc
, args
, argsi_count
, "The <count> must not be negative." );
2836 count
= countPtr
->val_
;
2839 if( beginPtr
== NullPtr
< ArgType
>( ) )
2841 if( countPtr
== NullPtr
< CountType
>( ) )
2845 if( endPtr
->val_
< 0 )
2847 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a span of integers and <begin> is omitted while <end> is negative.", coreLoc
, callLoc
);
2849 count
= 1 + endPtr
->val_
/ step
;
2853 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of integers and <begin> is omitted.", coreLoc
, callLoc
);
2856 begin
= endPtr
->val_
- ( count
- 1 ) * step
;
2858 else if( endPtr
== NullPtr
< ArgType
>( ) )
2860 begin
= beginPtr
->val_
;
2861 if( countPtr
== NullPtr
< CountType
>( ) )
2867 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of integers and <end> is omitted while <begin> exceeds %last.", coreLoc
, callLoc
);
2869 count
= ( last
- begin
) / step
+ 1;
2873 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of integers and <end> is omitted.", coreLoc
, callLoc
);
2879 if( countPtr
!= NullPtr
< CountType
>( ) )
2881 throw Exceptions::CoreRequirement( "It is an error to provide the <count> argument when constructing a range of integers from <begin> to <end>.", coreLoc
, args
.getLoc( argsi_count
) );
2884 begin
= beginPtr
->val_
;
2885 if( ( endPtr
->val_
>= begin
&& step
<= 0 )
2887 ( endPtr
->val_
<= begin
&& step
>= 0 ) )
2889 throw Exceptions::CoreOutOfRange( coreLoc
, args
, argsi_step
, "When <count> is omitted, the sign of <step> must agree with the order of <begin> and <end>." );
2891 count
= 1 + ( endPtr
->val_
- begin
) / step
;
2894 Kernel::ContRef cont
= evalState
->cont_
;
2897 cont
->takeValue( Lang::THE_CONS_NULL
,
2902 cont
->takeValue( RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListRange
< ArgType
>( begin
, step
, count
) ),
2907 catch( const NonLocalExit::NotThisType
& ball
)
2909 /* Never mind, see below. */
2914 typedef const Lang::Float ArgType
;
2916 RefCountPtr
< ArgType
> beginPtr
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi_begin
), true );
2917 RefCountPtr
< ArgType
> endPtr
= Helpers::down_cast_CoreArgument
< ArgType
>( coreLoc
, args
, argsi_end
, callLoc
, true );
2918 if( beginPtr
== NullPtr
< ArgType
>( ) && endPtr
== NullPtr
< ArgType
>( ) )
2920 throw Exceptions::CoreRequirement( "At least one of the arguments <begin> and <end> must be provided.", coreLoc
, callLoc
);
2922 RefCountPtr
< ArgType
> stepPtr
= Helpers::down_cast_CoreArgument
< ArgType
>( coreLoc
, args
, argsi_step
, callLoc
, true );
2923 RefCountPtr
< CountType
> countPtr
= Helpers::down_cast_CoreArgument
< CountType
>( coreLoc
, args
, argsi_count
, callLoc
, true );
2925 if( beginPtr
!= NullPtr
< ArgType
>( ) && endPtr
!= NullPtr
< ArgType
>( ) &&
2926 stepPtr
!= NullPtr
< ArgType
>( ) && countPtr
!= NullPtr
< CountType
>( ) )
2928 throw Exceptions::CoreRequirement( "At least one of the arguments must be omitted.", coreLoc
, callLoc
);
2931 ArgType::ValueType begin
= 0;
2932 ArgType::ValueType step
= 1;
2933 ArgType::ValueType last
= isSpan
? lastPtr
.down_cast
< ArgType
>( )->val_
: 0;
2936 if( stepPtr
!= NullPtr
< ArgType
>( ) )
2938 step
= stepPtr
->val_
;
2940 if( countPtr
!= NullPtr
< CountType
>( ) )
2942 if( countPtr
->val_
< 0 )
2944 throw Exceptions::CoreOutOfRange( coreLoc
, args
, argsi_count
, "The <count> must not be negative." );
2946 count
= countPtr
->val_
;
2949 if( beginPtr
== NullPtr
< ArgType
>( ) )
2951 if( countPtr
== NullPtr
< CountType
>( ) )
2955 if( endPtr
->val_
< 0 )
2957 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a span of floats and <begin> is omitted while <end> is negative.", coreLoc
, callLoc
);
2959 count
= 1 + static_cast< size_t >( endPtr
->val_
/ step
);
2963 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of floats and <begin> is omitted.", coreLoc
, callLoc
);
2966 begin
= endPtr
->val_
- ( count
- 1 ) * step
;
2968 else if( endPtr
== NullPtr
< ArgType
>( ) )
2970 begin
= beginPtr
->val_
;
2971 if( countPtr
== NullPtr
< CountType
>( ) )
2977 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of floats and <end> is omitted while <begin> exceeds %last.", coreLoc
, callLoc
);
2979 count
= 1 + static_cast< size_t >( ( last
- begin
) / step
);
2983 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of floats and <end> is omitted.", coreLoc
, callLoc
);
2989 begin
= beginPtr
->val_
;
2990 // When we reach here, we know that at most one of <step> and <count> is provided.
2991 if( countPtr
!= NullPtr
< CountType
>( ) )
2995 throw Exceptions::CoreOutOfRange( coreLoc
, args
, argsi_count
, "When <step> is omitted, the <count> be at least 2." );
2997 step
= ( endPtr
->val_
- begin
) / ( count
- 1 );
3001 /* If <step> is not provided, it defaults to 1, see above. */
3004 throw Exceptions::CoreOutOfRange( coreLoc
, args
, argsi_step
, "When <count> is omitted, <step> must not be zero." );
3006 ArgType::ValueType tmpCount
= 1 + ( endPtr
->val_
- begin
) / step
;
3013 if( tmpCount
> std::numeric_limits
< size_t >::max( ) )
3015 throw Exceptions::CoreOutOfRange( coreLoc
, args
, argsi_step
, "When <count> is omitted, too small <step> values cause overflow in the number of elements." );
3017 count
= static_cast< size_t >( tmpCount
);
3022 Kernel::ContRef cont
= evalState
->cont_
;
3025 cont
->takeValue( Lang::THE_CONS_NULL
,
3030 cont
->takeValue( RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListRange
< ArgType
>( begin
, step
, count
) ),
3035 catch( const NonLocalExit::NotThisType
& ball
)
3037 /* Never mind, see below. */
3042 typedef const Lang::Length ArgType
;
3044 RefCountPtr
< ArgType
> beginPtr
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi_begin
), true );
3045 RefCountPtr
< ArgType
> endPtr
= Helpers::down_cast_CoreArgument
< ArgType
>( coreLoc
, args
, argsi_end
, callLoc
, true );
3046 if( beginPtr
== NullPtr
< ArgType
>( ) && endPtr
== NullPtr
< ArgType
>( ) )
3048 throw Exceptions::CoreRequirement( "At least one of the arguments <begin> and <end> must be provided.", coreLoc
, callLoc
);
3050 RefCountPtr
< ArgType
> stepPtr
= Helpers::down_cast_CoreArgument
< ArgType
>( coreLoc
, args
, argsi_step
, callLoc
, true );
3051 RefCountPtr
< CountType
> countPtr
= Helpers::down_cast_CoreArgument
< CountType
>( coreLoc
, args
, argsi_count
, callLoc
, true );
3053 if( beginPtr
!= NullPtr
< ArgType
>( ) && endPtr
!= NullPtr
< ArgType
>( ) &&
3054 stepPtr
!= NullPtr
< ArgType
>( ) && countPtr
!= NullPtr
< CountType
>( ) )
3056 throw Exceptions::CoreRequirement( "At least one of the arguments must be omitted.", coreLoc
, callLoc
);
3059 ArgType::ValueType begin
= ArgType::ValueType( 0 );
3060 ArgType::ValueType step
= ArgType::ValueType( 1 ); /* This is a "default" value that one is not allowed to use! */
3061 ArgType::ValueType last
= isSpan
? lastPtr
.down_cast
< ArgType
>( )->get( ) : Concrete::ZERO_LENGTH
;
3064 if( stepPtr
!= NullPtr
< ArgType
>( ) )
3066 step
= stepPtr
->get( );
3068 if( countPtr
!= NullPtr
< CountType
>( ) )
3070 if( countPtr
->val_
< 0 )
3072 throw Exceptions::CoreOutOfRange( coreLoc
, args
, argsi_count
, "The <count> must not be negative." );
3074 count
= countPtr
->val_
;
3077 if( beginPtr
== NullPtr
< ArgType
>( ) )
3079 if( stepPtr
== NullPtr
< ArgType
>( ) )
3081 throw Exceptions::CoreRequirement( "The <step> must be provided when constructing a range of lengths when <begin> is omitted.", coreLoc
, callLoc
);
3083 if( countPtr
== NullPtr
< CountType
>( ) )
3087 if( endPtr
->get( ) < Concrete::ZERO_LENGTH
)
3089 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a span of lengths and <begin> is omitted while <end> is negative.", coreLoc
, callLoc
);
3091 count
= 1 + static_cast< size_t >( endPtr
->get( ) / step
);
3095 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of lengths and <begin> is omitted.", coreLoc
, callLoc
);
3098 begin
= endPtr
->get( ) - ( count
- 1 ) * step
;
3100 else if( endPtr
== NullPtr
< ArgType
>( ) )
3102 begin
= beginPtr
->get( );
3103 if( stepPtr
== NullPtr
< ArgType
>( ) )
3105 throw Exceptions::CoreRequirement( "The <step> must be provided when constructing a range of lengths when <end> is omitted.", coreLoc
, callLoc
);
3107 if( countPtr
== NullPtr
< CountType
>( ) )
3113 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of lengths and <end> is omitted while <begin> exceeds %last.", coreLoc
, callLoc
);
3115 count
= static_cast< size_t >( ( last
- begin
) / step
) + 1;
3119 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of lengths and <end> is omitted.", coreLoc
, callLoc
);
3125 begin
= beginPtr
->get( );
3126 if( stepPtr
== NullPtr
< ArgType
>( ) && countPtr
== NullPtr
< CountType
>( ) )
3128 throw Exceptions::CoreRequirement( "Either of the <step> and <count> arguments must be provided when constructing a range of lengths from <begin> to <end>.", coreLoc
, callLoc
);
3130 // When we reach here, we know that exactly one of <step> and <count> is provided.
3131 if( stepPtr
!= NullPtr
< ArgType
>( ) )
3135 throw Exceptions::CoreOutOfRange( coreLoc
, args
, argsi_step
, "When <count> is omitted, <step> must not be zero." );
3137 double tmpCount
= 1 + ( endPtr
->get( ) - begin
) / step
;
3144 if( tmpCount
> std::numeric_limits
< size_t >::max( ) )
3146 throw Exceptions::CoreOutOfRange( coreLoc
, args
, argsi_step
, "When <count> is omitted, too small <step> values cause overflow in the number of elements." );
3148 count
= static_cast< size_t >( tmpCount
);
3155 throw Exceptions::CoreOutOfRange( coreLoc
, args
, argsi_count
, "When <step> is omitted, the <count> be at least 2." );
3157 step
= ( endPtr
->get( ) - begin
) / ( count
- 1 );
3161 Kernel::ContRef cont
= evalState
->cont_
;
3164 cont
->takeValue( Lang::THE_CONS_NULL
,
3169 cont
->takeValue( RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListRange
< ArgType
>( begin
, step
, count
) ),
3174 catch( const NonLocalExit::NotThisType
& ball
)
3176 /* Never mind, see below. */
3179 throw Exceptions::CoreTypeMismatch( callLoc
, coreLoc
, args
, 0, Helpers::typeSetString( Lang::Integer::staticTypeName( ), Lang::Float::staticTypeName( ), Lang::Length::staticTypeName( ) ) );
3183 Kernel::Core_graph_cont_partitions::Core_graph_cont_partitions( RefCountPtr
< const Lang::Value
> nodes
, const Ast::SourceLocation
& nodesLoc
, RefCountPtr
< const Lang::Value
> edges
, const Ast::SourceLocation
& edgesLoc
, RefCountPtr
< const Kernel::GraphDomain
> domain
, const Kernel::ContRef
& cont
, const Ast::SourceLocation
& partitionsLoc
)
3184 : Kernel::Continuation( partitionsLoc
), nodes_( nodes
), nodesLoc_( nodesLoc
), edges_( edges
), edgesLoc_( edgesLoc
), domain_( domain
), cont_( cont
)
3187 Kernel::Core_graph_cont_partitions::~Core_graph_cont_partitions( )
3191 Kernel::Core_graph_cont_partitions::takeValue( const RefCountPtr
< const Lang::Value
> & partitionsUntyped
, Kernel::EvalState
* evalState
, bool dummy
) const
3193 typedef const Lang::SingleList ArgType
;
3194 RefCountPtr
< ArgType
> partitions
= Helpers::down_cast
< ArgType
>( partitionsUntyped
, "< Internal error situation in Core_graph_cont_partitions >" );
3196 evalState
->cont_
= Kernel::ContRef( new Kernel::ForcingListContinuation
3197 ( Kernel::ContRef( new Kernel::Core_graph_cont_nodes( edges_
, edgesLoc_
, domain_
, partitions
, cont_
, traceLoc_
, nodesLoc_
) ),
3200 Kernel::ContRef cont
= evalState
->cont_
;
3201 cont
->takeValue( nodes_
, evalState
);
3205 Kernel::Core_graph_cont_partitions::up( ) const
3210 RefCountPtr
< const char >
3211 Kernel::Core_graph_cont_partitions::description( ) const
3213 return strrefdup( "force list of partitions data" );
3217 Kernel::Core_graph_cont_partitions::gcMark( Kernel::GCMarkedSet
& marked
)
3219 const_cast< Lang::Value
* >( nodes_
.getPtr( ) )->gcMark( marked
);
3220 const_cast< Lang::Value
* >( edges_
.getPtr( ) )->gcMark( marked
);
3221 cont_
->gcMark( marked
);
3225 Kernel::Core_graph_cont_nodes::Core_graph_cont_nodes( RefCountPtr
< const Lang::Value
> edges
, const Ast::SourceLocation
& edgesLoc
, RefCountPtr
< const Kernel::GraphDomain
> domain
, const RefCountPtr
< const Lang::SingleList
> & partitions
, const Kernel::ContRef
& cont
, const Ast::SourceLocation
& partitionsLoc
, const Ast::SourceLocation
& nodesLoc
)
3226 : Kernel::Continuation( nodesLoc
), edges_( edges
), edgesLoc_( edgesLoc
), domain_( domain
), partitions_( partitions
), partitionsLoc_( partitionsLoc
), cont_( cont
)
3229 Kernel::Core_graph_cont_nodes::~Core_graph_cont_nodes( )
3233 Kernel::Core_graph_cont_nodes::takeValue( const RefCountPtr
< const Lang::Value
> & nodesUntyped
, Kernel::EvalState
* evalState
, bool dummy
) const
3235 typedef const Lang::SingleList ArgType
;
3236 RefCountPtr
< ArgType
> nodes
= Helpers::down_cast
< ArgType
>( nodesUntyped
, "< Internal error situation in Core_graph_cont_nodes >" );
3238 evalState
->cont_
= Kernel::ContRef( new Kernel::ForcingListContinuation
3239 ( Kernel::ContRef( new Kernel::Core_graph_cont_edges( nodes
, domain_
, partitions_
, cont_
, traceLoc_
, partitionsLoc_
, edgesLoc_
) ),
3242 Kernel::ContRef cont
= evalState
->cont_
;
3243 cont
->takeValue( edges_
, evalState
);
3247 Kernel::Core_graph_cont_nodes::up( ) const
3252 RefCountPtr
< const char >
3253 Kernel::Core_graph_cont_nodes::description( ) const
3255 return strrefdup( "force list of node data" );
3259 Kernel::Core_graph_cont_nodes::gcMark( Kernel::GCMarkedSet
& marked
)
3261 const_cast< Lang::Value
* >( edges_
.getPtr( ) )->gcMark( marked
);
3262 cont_
->gcMark( marked
);
3266 Kernel::Core_graph_cont_edges::Core_graph_cont_edges( RefCountPtr
< const Lang::SingleList
> nodes
, RefCountPtr
< const Kernel::GraphDomain
> domain
, const RefCountPtr
< const Lang::SingleList
> & partitions
, const Kernel::ContRef
& cont
, const Ast::SourceLocation
& nodesLoc
, const Ast::SourceLocation
& partitionsLoc
, const Ast::SourceLocation
& edgesLoc
)
3267 : Kernel::Continuation( edgesLoc
), nodes_( nodes
), domain_( domain
), partitions_( partitions
), nodesLoc_( nodesLoc
), partitionsLoc_( partitionsLoc
), cont_( cont
)
3270 Kernel::Core_graph_cont_edges::~Core_graph_cont_edges( )
3274 Kernel::Core_graph_cont_edges::takeValue( const RefCountPtr
< const Lang::Value
> & edgesUntyped
, Kernel::EvalState
* evalState
, bool dummy
) const
3276 typedef const Lang::SingleList ArgType
;
3277 RefCountPtr
< ArgType
> edges
= Helpers::down_cast
< ArgType
>( edgesUntyped
, "< Internal error situation in Core_graph_cont_edges >" );
3279 RefCountPtr
< const Lang::Graph
> graph
= constructGraph( edges
, evalState
->env_
, evalState
->dyn_
);
3281 evalState
->cont_
= cont_
;
3282 cont_
->takeValue( graph
,
3287 Kernel::Core_graph_cont_edges::up( ) const
3292 RefCountPtr
< const char >
3293 Kernel::Core_graph_cont_edges::description( ) const
3295 return strrefdup( "force list of edge data" );
3299 Kernel::Core_graph_cont_edges::gcMark( Kernel::GCMarkedSet
& marked
)
3301 const_cast< Lang::SingleList
* >( nodes_
.getPtr( ) )->gcMark( marked
);
3302 cont_
->gcMark( marked
);
3310 NodeDataReceiverFormals theNodeDataReceiverFormals
;
3311 EdgeDataReceiverFormals theEdgeDataReceiverFormals
;
3316 RefCountPtr
< const Lang::Graph
>
3317 Kernel::Core_graph_cont_edges::constructGraph( const RefCountPtr
< const Lang::SingleList
> & edges
, Kernel::PassedEnv env
, Kernel::PassedDyn dyn
) const
3319 std::list
< Kernel::NodeData
> nodeData
;
3320 std::list
< Kernel::EdgeData
> edgeData
;
3323 RefCountPtr
< const Lang::SingleListPair
> p
= nodes_
.down_cast
< const Lang::SingleListPair
>( );
3324 while( p
!= NullPtr
< const Lang::SingleListPair
>( ) ){
3325 RefCountPtr
< const Lang::Value
> key
= RefCountPtr
< const Lang::Value
>( NullPtr
< const Lang::Value
>( ) );
3326 RefCountPtr
< const Lang::Value
> value
= Lang::THE_VOID
;
3327 RefCountPtr
< const Lang::Value
> partition
= Lang::THE_VOID
;
3331 key
= p
->car_
->tryVal
< const Lang::Symbol
>( );
3334 catch( const NonLocalExit::NotThisType
& ball
)
3336 /* Never mind, see below. */
3341 key
= p
->car_
->tryVal
< const Lang::Integer
>( );
3344 catch( const NonLocalExit::NotThisType
& ball
)
3346 /* Never mind, see below. */
3351 RefCountPtr
< const Lang::Structure
> node
= p
->car_
->tryVal
< const Lang::Structure
>( );
3354 * Argument 2: partition
3356 Kernel::Arguments
args( & theNodeDataReceiverFormals
);
3357 node
->argList_
->bind( & args
, node
->values_
, env
, dyn
);
3358 args
.applyDefaults( nodesLoc_
);
3359 key
= args
.getValue( 0 );
3360 value
= args
.getValue( 1 );
3361 partition
= args
.getValue( 2 );
3364 catch( const NonLocalExit::NotThisType
& ball
)
3366 /* Never mind, see below. */
3369 throw Exceptions::TypeMismatch( traceLoc_
, "Node element in graph construction", p
->car_
->getUntyped( )->getTypeName( ), Exceptions::GraphKeyTypeMismatch::expectedTypeOrStructure
);
3372 nodeData
.push_back( Kernel::NodeData( key
, value
, partition
) );
3373 p
= p
->cdr_
.down_cast
< const Lang::SingleListPair
>( );
3378 RefCountPtr
< const Lang::SingleListPair
> p
= edges
.down_cast
< const Lang::SingleListPair
>( );
3379 while( p
!= NullPtr
< const Lang::SingleListPair
>( ) ){
3380 RefCountPtr
< const Lang::Structure
> edge
= p
->car_
->getVal
< const Lang::Structure
>( "EdgeData for graph construction." );
3381 /* Argument 0: source
3382 * Argument 1: target
3384 * Argument 3: directed
3386 Kernel::Arguments
args( & theEdgeDataReceiverFormals
);
3387 edge
->argList_
->bind( & args
, edge
->values_
, env
, dyn
);
3388 args
.applyDefaults( traceLoc_
);
3391 RefCountPtr
< const Lang::Boolean
> directedBoolean
= args
.getValue( 4 ).down_cast
< const Lang::Boolean
>( );
3392 if( directedBoolean
!= NullPtr
< const Lang::Boolean
>( ) ){
3393 directed
= directedBoolean
->val_
;
3395 RefCountPtr
< const Lang::Void
> directedVoid
= args
.getValue( 4 ).down_cast
< const Lang::Void
>( );
3396 if( directedVoid
!= NullPtr
< const Lang::Void
>( ) ){
3397 if( domain_
->directed( ) && not domain_
->undirected( ) )
3399 else if( not domain_
->directed( ) && domain_
->undirected( ) )
3402 throw Exceptions::MiscellaneousRequirement( traceLoc_
, "The EdgeData field 'directed' must be specified since the graph domain does not determine a default interpretation." );
3404 throw Exceptions::TypeMismatch( traceLoc_
, "EdgeData field 'directed'.", args
.getValue( 3 )->getTypeName( ), Helpers::typeSetString( Lang::Boolean::staticTypeName( ), Lang::Void::staticTypeName( ) ) );
3409 RefCountPtr
< const Lang::Value
> sourceKey
= args
.getValue( 0 );
3410 RefCountPtr
< const Lang::Value
> targetKey
= args
.getValue( 1 );
3411 RefCountPtr
< const Lang::Value
> value
= args
.getValue( 2 );
3412 RefCountPtr
< const Lang::Value
> label
= args
.getValue( 3 );
3413 edgeData
.push_back( Kernel::EdgeData( directed
, sourceKey
, targetKey
, value
, label
) );
3414 p
= p
->cdr_
.down_cast
< const Lang::SingleListPair
>( );
3418 return Helpers::graphFromNodeEdgeData( *domain_
, partitions_
, nodeData
, edgeData
, partitionsLoc_
, traceLoc_
);
3422 Kernel::Core_walk_cont_edges::Core_walk_cont_edges( const RefCountPtr
< const Lang::Graph
> & graph
, const RefCountPtr
< const Lang::Node
> & first
, const RefCountPtr
< const Lang::Node
> & last
, const Ast::SourceLocation
& edgesLoc
, const Kernel::ContRef
& cont
, const Ast::SourceLocation
& callLoc
)
3423 : Kernel::Continuation( edgesLoc
), graph_( graph
), first_( first
), last_( last
), callLoc_( callLoc
), cont_( cont
)
3426 Kernel::Core_walk_cont_edges::~Core_walk_cont_edges( )
3430 Kernel::Core_walk_cont_edges::takeValue( const RefCountPtr
< const Lang::Value
> & edgesUntyped
, Kernel::EvalState
* evalState
, bool dummy
) const
3432 typedef const Lang::SingleList ArgType
;
3433 RefCountPtr
< ArgType
> edges
= Helpers::down_cast
< ArgType
>( edgesUntyped
, "< Internal error situation in Core_walk_cont_edges >" );
3435 RefCountPtr
< const Lang::Walk
> walk( new Lang::Walk( graph_
, first_
, last_
, edges
, traceLoc_
, callLoc_
) );
3437 evalState
->cont_
= cont_
;
3438 cont_
->takeValue( walk
,
3443 Kernel::Core_walk_cont_edges::up( ) const
3448 RefCountPtr
< const char >
3449 Kernel::Core_walk_cont_edges::description( ) const
3451 return strrefdup( "force list of walk edges" );
3455 Kernel::Core_walk_cont_edges::gcMark( Kernel::GCMarkedSet
& marked
)
3457 const_cast< Lang::Graph
* >( graph_
.getPtr( ) )->gcMark( marked
);
3458 const_cast< Lang::Node
* >( first_
.getPtr( ) )->gcMark( marked
);
3459 const_cast< Lang::Node
* >( last_
.getPtr( ) )->gcMark( marked
);
3460 cont_
->gcMark( marked
);
3465 * To avoid problems with initialization order (Kernel::THE_VOID_VARIABLE has to be initialized first), we first
3466 * initialize with an ugly null value, and then set the correct value when the real function is registered below.
3468 RefCountPtr
< const Lang::CoreFunction
> Lang::THE_FUNCTION_RANGE
= RefCountPtr
< const Lang::CoreFunction
>( NullPtr
< const Lang::CoreFunction
>( ) );
3471 Kernel::registerCore_construct( Kernel::Environment
* env
)
3473 Lang::THE_FUNCTION_RANGE
= RefCountPtr
< const Lang::CoreFunction
>( new Lang::Core_range( Lang::THE_NAMESPACE_Shapes_Data
, "range" ) );
3475 env
->initDefineCoreFunction( new Lang::Core_cons( Lang::THE_NAMESPACE_Shapes_Data
, "cons" ) );
3476 env
->initDefineCoreFunction( new Lang::Core_list( Lang::THE_NAMESPACE_Shapes_Data
, "list" ) );
3477 env
->initDefineCoreFunction( new Lang::Core_unlist( Lang::THE_NAMESPACE_Shapes_Data
, "unlist" ) );
3478 env
->initDefineCoreFunction( new Lang::Core_isnil( Lang::THE_NAMESPACE_Shapes_Data
, "nil?" ) );
3479 env
->initDefineCoreFunction( Lang::THE_FUNCTION_RANGE
);
3480 env
->initDefineCoreFunction( new Lang::Core_span( Lang::THE_NAMESPACE_Shapes_Data
, "span" ) );
3481 env
->initDefineCoreFunction( new Lang::Core_shift( Lang::THE_NAMESPACE_Shapes_Geometry
, "shift" ) );
3482 env
->initDefineCoreFunction( new Lang::Core_shift3d( Lang::THE_NAMESPACE_Shapes_Geometry3D
, "shift" ) );
3483 env
->initDefineCoreFunction( new Lang::Core_rotate( Lang::THE_NAMESPACE_Shapes_Geometry
, "rotate" ) );
3484 env
->initDefineCoreFunction( new Lang::Core_rotate3d( Lang::THE_NAMESPACE_Shapes_Geometry3D
, "rotate" ) );
3485 env
->initDefineCoreFunction( new Lang::Core_scale( Lang::THE_NAMESPACE_Shapes_Geometry
, "scale" ) );
3486 env
->initDefineCoreFunction( new Lang::Core_scale3d( Lang::THE_NAMESPACE_Shapes_Geometry3D
, "scale" ) );
3487 env
->initDefineCoreFunction( new Lang::Core_affinetransform( Lang::THE_NAMESPACE_Shapes_Geometry
, "affinetransform" ) );
3488 env
->initDefineCoreFunction( new Lang::Core_affinetransform3d( Lang::THE_NAMESPACE_Shapes_Geometry3D
, "affinetransform" ) );
3489 env
->initDefineCoreFunction( new Lang::Core_inverse( Lang::THE_NAMESPACE_Shapes_Geometry
, "inverse" ) );
3490 env
->initDefineCoreFunction( new Lang::Core_inverse3d( Lang::THE_NAMESPACE_Shapes_Geometry3D
, "inverse" ) );
3492 env
->initDefineCoreFunction( new Lang::Core_formxo( Lang::THE_NAMESPACE_Shapes_Graphics_PDF
, "formxo" ) );
3493 env
->initDefineCoreFunction( new Lang::Core_importRasterImage( Lang::THE_NAMESPACE_Shapes_Graphics
, "import_raster" ) );
3494 env
->initDefineCoreFunction( new Lang::Core_transparencygroup( Lang::THE_NAMESPACE_Shapes_Graphics
, "tgroup" ) );
3496 env
->initDefineCoreFunction( new Lang::Core_tag( Lang::THE_NAMESPACE_Shapes_Graphics_Tag
, "tag" ) );
3497 env
->initDefineCoreFunction( new Lang::Core_find( Lang::THE_NAMESPACE_Shapes_Graphics_Tag
, "find" ) );
3498 env
->initDefineCoreFunction( new Lang::Core_findall( Lang::THE_NAMESPACE_Shapes_Graphics_Tag
, "findall" ) );
3500 env
->initDefineCoreFunction( new Lang::Core_ambient_light( Lang::THE_NAMESPACE_Shapes_Traits_Light
, "ambient_light" ) );
3501 env
->initDefineCoreFunction( new Lang::Core_specular_light( Lang::THE_NAMESPACE_Shapes_Traits_Light
, "specular_light" ) );
3502 env
->initDefineCoreFunction( new Lang::Core_distant_light( Lang::THE_NAMESPACE_Shapes_Traits_Light
, "distant_light" ) );
3503 env
->initDefineCoreFunction( new Lang::Core_phong( Lang::THE_NAMESPACE_Shapes_Traits_Light
, "phong" ) );
3505 env
->initDefineCoreFunction( new Lang::Core_vector( Lang::THE_NAMESPACE_Shapes_Data
, "vector" ) );
3506 env
->initDefineCoreFunction( new Lang::Core_graph( Lang::THE_NAMESPACE_Shapes_Data
, "graph" ) );
3507 env
->initDefineCoreFunction( new Lang::Core_walk( Lang::THE_NAMESPACE_Shapes_Data
, "walk" ) );
3508 env
->initDefineCoreFunction( new Lang::Core_importPDFpages( Lang::THE_NAMESPACE_Shapes_Graphics
, "import" ) );
3510 env
->initDefineCoreFunction( new Lang::Core_svg_path( Lang::THE_NAMESPACE_Shapes_Geometry
, "svg_path" ) );
3512 env
->initDefineCoreFunction( new Lang::Core_sprintf( Lang::THE_NAMESPACE_Shapes_String
, "sprintf" ) );
3513 env
->initDefineCoreFunction( new Lang::Core_strftime( Lang::THE_NAMESPACE_Shapes_String
, "strftime" ) );
3515 env
->initDefineCoreFunction( new Lang::Core_newrandom( Lang::THE_NAMESPACE_Shapes_Numeric_Random
, "newRandom" ) );
3516 env
->initDefineCoreFunction( new Lang::Core_devrandom( Lang::THE_NAMESPACE_Shapes_Numeric_Random
, "devRandom" ) );
3518 env
->initDefineCoreFunction( new Lang::Core_destination( Lang::THE_NAMESPACE_Shapes_Graphics_PDF
, "destination" ) );
3520 env
->initDefineCoreFunction( new Lang::Core_textrenderingmode( Lang::THE_NAMESPACE_Shapes_Text
, "textmode" ) );
3521 env
->initDefineCoreFunction( new Lang::Core_manualkern( Lang::THE_NAMESPACE_Shapes_Text
, "kerning" ) );
3522 env
->initDefineCoreFunction( new Lang::Core_automatickern( Lang::THE_NAMESPACE_Shapes_Text
, "kern" ) );
3524 env
->initDefineCoreFunction( new Lang::Core_importFont( Lang::THE_NAMESPACE_Shapes_Text
, "font" ) );
3526 env
->initDefineCoreFunction( new Lang::Core_Unicode( Lang::THE_NAMESPACE_Shapes_String
, "Unicode" ) );
3527 env
->initDefineCoreFunction( new Lang::Core_AdobeGlyphList( Lang::THE_NAMESPACE_Shapes_String
, "AdobeGlyphList" ) );