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 Henrik Tidefelt
21 #include "Shapes_Helpers_decls.h"
23 #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 "shapesscanner.h"
40 #include "rasterloaders.h"
41 #include "glyphlist.h"
47 #include FT_FREETYPE_H
49 #ifdef HAVE_FONTCONFIG
50 #include <fontconfig/fontconfig.h>
60 using namespace Shapes
;
67 RasterLoader_PNG theRasterLoader_PNG
;
68 RasterLoader_JPEG theRasterLoader_JPEG
;
69 #ifdef HAVE_FONTCONFIG
70 class AutoDestroyFcPattern
74 AutoDestroyFcPattern( FcPattern
* pat
)
77 ~AutoDestroyFcPattern( )
81 FcPatternDestroy( pat_
);
89 class AutoDestroyFcFontSet
93 AutoDestroyFcFontSet( FcFontSet
* set
)
96 ~AutoDestroyFcFontSet( )
100 FcFontSetDestroy( set_
);
114 class Core_tag
: public Lang::CoreFunction
117 Core_tag( const char * title
)
118 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
120 formals_
->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE
);
121 formals_
->appendEvaluatedCoreFormal( "obj", Kernel::THE_SLOT_VARIABLE
);
122 formals_
->appendEvaluatedCoreFormal( "transform", Kernel::THE_TRUE_VARIABLE
); // this argument means "transform if applicable"
123 formals_
->appendEvaluatedCoreFormal( "draw", Kernel::THE_TRUE_VARIABLE
); // this argument means "draw if applicable"
127 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
129 args
.applyDefaults( );
131 typedef const Lang::Symbol KeyType
;
132 RefCountPtr
< KeyType
> key
= Helpers::down_cast_CoreArgument
< KeyType
>( title_
, args
, 0, callLoc
);
133 bool tryTransform
= Helpers::down_cast_CoreArgument
< const Lang::Boolean
>( title_
, args
, 2, callLoc
)->val_
;
134 bool tryDraw
= Helpers::down_cast_CoreArgument
< const Lang::Boolean
>( title_
, args
, 3, callLoc
)->val_
;
136 if( tryDraw
&& ! tryTransform
)
138 throw Exceptions::CoreOutOfRange( title_
, args
, 3, "A tagged object which does not transform cannot be drawn." );
147 typedef const Lang::Drawable2D ArgType
;
149 RefCountPtr
< ArgType
> obj
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi
) );
151 Kernel::ContRef cont
= evalState
->cont_
;
152 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::TaggedDrawable2D( key
, obj
) ),
156 catch( const NonLocalExit::NotThisType
& ball
)
158 // Never mind, see below
163 typedef const Lang::Drawable3D ArgType
;
165 RefCountPtr
< ArgType
> obj
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi
) );
167 Kernel::ContRef cont
= evalState
->cont_
;
168 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::TaggedDrawable3D( key
, obj
) ),
172 catch( const NonLocalExit::NotThisType
& ball
)
174 // Never mind, see below
182 typedef const Lang::Geometric2D ArgType
;
184 RefCountPtr
< ArgType
> obj
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi
) );
186 Kernel::ContRef cont
= evalState
->cont_
;
187 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::TaggedGeometric2D( key
, obj
) ),
191 catch( const NonLocalExit::NotThisType
& ball
)
193 // Never mind, see below
198 typedef const Lang::Geometric3D ArgType
;
200 RefCountPtr
< ArgType
> obj
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi
) );
202 Kernel::ContRef cont
= evalState
->cont_
;
203 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::TaggedGeometric3D( key
, obj
) ),
207 catch( const NonLocalExit::NotThisType
& ball
)
209 // Never mind, see below
214 // As a last resort, we tag any value.
215 // We return a Drawable2D. Use immerse to make it 3D.
216 Kernel::ContRef cont
= evalState
->cont_
;
217 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::TaggedValue2D( key
, args
.getValue( argsi
) ) ),
223 // This function is in this file just because it i so related to Core_tag.
224 class Core_find
: public Lang::CoreFunction
227 Core_find( const char * title
)
228 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
230 formals_
->appendEvaluatedCoreFormal( "container", Kernel::THE_SLOT_VARIABLE
);
231 formals_
->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE
);
235 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
237 args
.applyDefaults( );
239 typedef const Lang::Symbol KeyType
;
240 RefCountPtr
< KeyType
> key
= Helpers::down_cast_CoreArgument
< KeyType
>( title_
, args
, 1, callLoc
);
246 typedef const Lang::Drawable2D ContainerType
;
248 RefCountPtr
< ContainerType
> container
= Helpers::try_cast_CoreArgument
< ContainerType
>( args
.getValue( argsi
) );
250 if( ! container
->findOneTag( evalState
, key
->getKey( ), Lang::THE_2D_IDENTITY
) )
252 throw Exceptions::CoreOutOfRange( title_
, args
, 1, "Key not found." );
256 catch( const NonLocalExit::NotThisType
& ball
)
258 // Never mind, see below
263 typedef const Lang::Drawable3D ContainerType
;
265 RefCountPtr
< ContainerType
> container
= Helpers::try_cast_CoreArgument
< ContainerType
>( args
.getValue( argsi
) );
267 if( ! container
->findOneTag( evalState
, key
->getKey( ), Lang::THE_3D_IDENTITY
) )
269 throw Exceptions::CoreOutOfRange( title_
, args
, 1, "Key not found." );
273 catch( const NonLocalExit::NotThisType
& ball
)
275 // Never mind, see below
278 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, argsi
, Helpers::typeSetString( Lang::Drawable2D::staticTypeName( ), Lang::Drawable3D::staticTypeName( ) ) );
282 // This function is in this file just because it i so related to Core_tag.
283 class Core_findall
: public Lang::CoreFunction
286 Core_findall( const char * title
)
287 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
289 formals_
->appendEvaluatedCoreFormal( "container", Kernel::THE_SLOT_VARIABLE
);
290 formals_
->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE
);
294 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
296 args
.applyDefaults( );
298 typedef const Lang::Symbol KeyType
;
299 RefCountPtr
< KeyType
> key
= Helpers::down_cast_CoreArgument
< KeyType
>( title_
, args
, 1, callLoc
);
305 typedef const Lang::Drawable2D ContainerType
;
307 RefCountPtr
< ContainerType
> container
= Helpers::try_cast_CoreArgument
< ContainerType
>( args
.getValue( argsi
) );
309 std::vector
< Kernel::ValueRef
> * dst
= new std::vector
< Kernel::ValueRef
>;
310 container
->findTags( dst
, evalState
->dyn_
, key
->getKey( ), Lang::THE_2D_IDENTITY
);
312 Kernel::ContRef cont
= evalState
->cont_
;
313 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::VectorFunction( dst
) ),
317 catch( const NonLocalExit::NotThisType
& ball
)
319 // Never mind, see below
324 typedef const Lang::Drawable3D ContainerType
;
326 RefCountPtr
< ContainerType
> container
= Helpers::try_cast_CoreArgument
< ContainerType
>( args
.getValue( argsi
) );
328 std::vector
< Kernel::ValueRef
> * dst
= new std::vector
< Kernel::ValueRef
>;
329 container
->findTags( dst
, evalState
->dyn_
, key
->getKey( ), Lang::THE_3D_IDENTITY
);
331 Kernel::ContRef cont
= evalState
->cont_
;
332 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::VectorFunction( dst
) ),
336 catch( const NonLocalExit::NotThisType
& ball
)
338 // Never mind, see below
341 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, argsi
, Helpers::typeSetString( Lang::Drawable2D::staticTypeName( ), Lang::Drawable3D::staticTypeName( ) ) );
345 class Core_phong
: public Lang::CoreFunction
348 Core_phong( const char * title
) : CoreFunction( title
) { }
350 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
352 const size_t ARITY
= 1;
353 CHECK_ARITY( args
, ARITY
, title_
);
355 typedef const Lang::Float ArgType
;
356 double exponent
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 0, callLoc
)->val_
;
359 throw Exceptions::CoreOutOfRange( title_
, args
, 0, "The Phong exponent should be greater than 0." );
362 Kernel::ContRef cont
= evalState
->cont_
;
363 cont
->takeValue( Kernel::ValueRef( new Lang::SpecularReflectionTerm( 1., exponent
) ),
368 class Core_cons
: public Lang::CoreFunction
371 Core_cons( const char * title
)
372 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), false ) )
374 formals_
->appendEvaluatedCoreFormal( "car", Kernel::THE_SLOT_VARIABLE
);
375 formals_
->appendEvaluatedCoreFormal( "cdr", Kernel::THE_SLOT_VARIABLE
);
378 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
380 const size_t ARITY
= 2;
381 CHECK_ARITY( args
, ARITY
, title_
);
383 Kernel::ContRef cont
= evalState
->cont_
;
384 cont
->takeValue( Kernel::ValueRef( new Lang::ConsPair( args
.getHandle( 0 ),
385 args
.getHandle( 1 ) ) ),
390 class Core_list
: public Lang::CoreFunction
393 Core_list( const char * title
) : CoreFunction( title
) { }
395 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
397 RefCountPtr
< const Lang::SingleList
> res
= Lang::THE_CONS_NULL
;
398 if( ! args
.empty( ) )
400 for( size_t i
= args
.size( ) - 1; ; --i
)
402 res
= RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListPair( args
.getHandle( i
), res
) );
410 Kernel::ContRef cont
= evalState
->cont_
;
411 cont
->takeValue( res
,
416 class Core_unlist
: public Lang::CoreFunction
418 Kernel::UnnamedStructureFactory argListFactory_
;
420 Core_unlist( const char * title
) : CoreFunction( title
) { }
422 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
424 const size_t ARITY
= 1;
425 CHECK_ARITY( args
, ARITY
, title_
);
427 typedef const Lang::SingleList ArgType
;
429 Kernel::ContRef cont
= evalState
->cont_
;
430 cont
->takeValue( argListFactory_
.build( Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 0, callLoc
) ),
435 class Core_isnull
: public Lang::CoreFunction
438 Core_isnull( const char * title
) : CoreFunction( title
) { }
440 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
442 const size_t ARITY
= 1;
443 CHECK_ARITY( args
, ARITY
, title_
);
445 RefCountPtr
< const Lang::Value
> aUntyped
= args
.getValue( 0 );
447 Kernel::ContRef cont
= evalState
->cont_
;
448 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::Boolean( dynamic_cast< const Lang::SingleListNull
* >( args
.getValue( 0 ).getPtr( ) ) != 0 ) ),
453 class Core_span
: public Lang::CoreFunction
456 Core_span( const char * title
)
457 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), false ) )
459 formals_
->appendEvaluatedCoreFormal( "begin", Kernel::THE_VOID_VARIABLE
);
460 formals_
->appendEvaluatedCoreFormal( "end", Kernel::THE_VOID_VARIABLE
);
461 formals_
->appendEvaluatedCoreFormal( "step", Kernel::THE_VOID_VARIABLE
);
462 formals_
->appendEvaluatedCoreFormal( "count", Kernel::THE_VOID_VARIABLE
);
465 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
467 args
.applyDefaults( );
469 Kernel::ContRef cont
= evalState
->cont_
;
470 cont
->takeValue( Kernel::ValueRef( new Lang::Span( args
.getHandle( 0 ), args
.getHandle( 1 ), args
.getHandle( 2 ), args
.getHandle( 3 ) ) ),
475 class Core_affinetransform
: public Lang::CoreFunction
478 Core_affinetransform( const char * title
) : CoreFunction( title
) { }
480 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
482 const size_t ARITY
= 3;
483 CHECK_ARITY( args
, ARITY
, title_
);
485 typedef const Lang::FloatPair ArgType0
;
486 typedef const Lang::FloatPair ArgType1
;
487 typedef const Lang::Coords2D ArgType2
;
489 RefCountPtr
< ArgType0
> argx
= Helpers::down_cast_CoreArgument
< ArgType0
>( title_
, args
, 0, callLoc
);
490 RefCountPtr
< ArgType1
> argy
= Helpers::down_cast_CoreArgument
< ArgType1
>( title_
, args
, 1, callLoc
);
491 RefCountPtr
< ArgType2
> arg1
= Helpers::down_cast_CoreArgument
< ArgType2
>( title_
, args
, 2, callLoc
);
493 Kernel::ContRef cont
= evalState
->cont_
;
494 cont
->takeValue( Kernel::ValueRef( new Lang::Transform2D( argx
->x_
, argx
->y_
, argy
->x_
, argy
->y_
, arg1
->x_
.get( ), arg1
->y_
.get( ) ) ),
499 class Core_affinetransform3D
: public Lang::CoreFunction
502 Core_affinetransform3D( const char * title
) : CoreFunction( title
) { }
504 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
506 const size_t ARITY
= 4;
507 CHECK_ARITY( args
, ARITY
, title_
);
509 typedef const Lang::FloatTriple ArgType0
;
510 typedef const Lang::FloatTriple ArgType1
;
511 typedef const Lang::FloatTriple ArgType2
;
512 typedef const Lang::Coords3D ArgType3
;
514 RefCountPtr
< ArgType0
> argx
= Helpers::down_cast_CoreArgument
< ArgType0
>( title_
, args
, 0, callLoc
);
515 RefCountPtr
< ArgType1
> argy
= Helpers::down_cast_CoreArgument
< ArgType1
>( title_
, args
, 1, callLoc
);
516 RefCountPtr
< ArgType2
> argz
= Helpers::down_cast_CoreArgument
< ArgType2
>( title_
, args
, 2, callLoc
);
517 RefCountPtr
< ArgType3
> arg1
= Helpers::down_cast_CoreArgument
< ArgType3
>( title_
, args
, 3, callLoc
);
519 Kernel::ContRef cont
= evalState
->cont_
;
520 cont
->takeValue( Kernel::ValueRef( new Lang::Transform3D( argx
->x_
, argx
->y_
, argx
->z_
,
521 argy
->x_
, argy
->y_
, argy
->z_
,
522 argz
->x_
, argz
->y_
, argz
->z_
,
523 arg1
->x_
.get( ), arg1
->y_
.get( ), arg1
->z_
.get( ) ) ),
528 class Core_shift
: public Lang::CoreFunction
531 Core_shift( const char * title
) : CoreFunction( title
) { }
533 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
535 const size_t ARITY
= 1;
536 CHECK_ARITY( args
, ARITY
, title_
);
538 Kernel::ContRef cont
= evalState
->cont_
;
543 typedef const Lang::Coords2D ArgType1
;
544 RefCountPtr
< ArgType1
> arg1
= Helpers::try_cast_CoreArgument
< ArgType1
>( args
.getValue( i
) );
545 cont
->takeValue( Kernel::ValueRef( new Lang::Transform2D( 1, 0, 0, 1, arg1
->x_
.get( ), arg1
->y_
.get( ) ) ),
549 catch( const NonLocalExit::NotThisType
& ball
)
551 // Never mind, see below
556 typedef const Lang::Coords3D ArgType1
;
557 RefCountPtr
< ArgType1
> arg1
= Helpers::try_cast_CoreArgument
< ArgType1
>( args
.getValue( i
) );
558 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( ) ) ),
562 catch( const NonLocalExit::NotThisType
& ball
)
564 // Never mind, see below
567 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, i
, Helpers::typeSetString( Lang::Coords2D::staticTypeName( ), Lang::Coords3D::staticTypeName( ) ) );
571 class Core_rotate
: public Lang::CoreFunction
574 Core_rotate( const char * title
)
575 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
577 formals_
->appendEvaluatedCoreFormal( "angle", Kernel::THE_SLOT_VARIABLE
);
580 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
582 args
.applyDefaults( );
586 typedef const Lang::Float ArgType1
;
587 RefCountPtr
< ArgType1
> arg1
= Helpers::down_cast_CoreArgument
< ArgType1
>( title_
, args
, i
, callLoc
);
589 double c
= cos( arg1
->val_
);
590 double s
= sin( arg1
->val_
);
591 Kernel::ContRef cont
= evalState
->cont_
;
592 cont
->takeValue( Kernel::ValueRef( new Lang::Transform2D( c
, s
, -s
, c
, 0, 0 ) ),
597 class Core_rotate3d
: public Lang::CoreFunction
600 Core_rotate3d( const char * title
)
601 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
603 formals_
->appendEvaluatedCoreFormal( "dir", Kernel::THE_SLOT_VARIABLE
);
604 formals_
->appendEvaluatedCoreFormal( "angle", Kernel::THE_SLOT_VARIABLE
);
607 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
609 args
.applyDefaults( );
613 typedef const Lang::FloatTriple ArgType1
;
614 RefCountPtr
< ArgType1
> dir
= Helpers::down_cast_CoreArgument
< ArgType1
>( title_
, args
, i
, callLoc
);
615 if( dir
->x_
== 0 && dir
->y_
== 0 && dir
->z_
== 0 )
617 throw Exceptions::CoreOutOfRange( title_
, args
, i
, "The rotation direction is degenerate, that is (0,0,0)." );
622 typedef const Lang::Float ArgType2
;
623 RefCountPtr
< ArgType2
> angle
= Helpers::down_cast_CoreArgument
< ArgType2
>( title_
, args
, i
, callLoc
);
625 double r
= sqrt( dir
->x_
* dir
->x_
+ dir
->y_
* dir
->y_
+ dir
->z_
* dir
->z_
);
626 double x
= dir
->x_
/ r
;
627 double y
= dir
->y_
/ r
;
628 double z
= dir
->z_
/ r
;
632 double c
= cos( angle
->val_
);
633 double s
= sin( angle
->val_
);
634 Kernel::ContRef cont
= evalState
->cont_
;
635 cont
->takeValue( Kernel::ValueRef( new Lang::Transform3D( x2
+(y2
+z2
)*c
, x
*y
*(1-c
)+z
*s
, x
*z
*(1-c
)-y
*s
,
636 x
*y
*(1-c
)-z
*s
, y2
+(x2
+z2
)*c
, y
*z
*(1-c
)+x
*s
,
637 x
*z
*(1-c
)+y
*s
, y
*z
*(1-c
)-x
*s
, z2
+(x2
+y2
)*c
,
643 class Core_scale
: public Lang::CoreFunction
646 Core_scale( const char * title
)
647 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
649 Kernel::VariableHandle
one( new Kernel::Variable( RefCountPtr
< const Lang::Value
>( new Lang::Float( 1 ) ) ) );
651 formals_
->appendEvaluatedCoreFormal( "r", one
);
652 formals_
->appendEvaluatedCoreFormal( "x", one
);
653 formals_
->appendEvaluatedCoreFormal( "y", one
);
656 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
658 args
.applyDefaults( );
660 typedef const Lang::Float ArgType
;
661 RefCountPtr
< ArgType
> argr
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 0, callLoc
);
662 RefCountPtr
< ArgType
> argx
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 1, callLoc
);
663 RefCountPtr
< ArgType
> argy
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 2, callLoc
);
665 Kernel::ContRef cont
= evalState
->cont_
;
666 cont
->takeValue( Kernel::ValueRef( new Lang::Transform2D( argr
->val_
* argx
->val_
, 0,
667 0, argr
->val_
* argy
->val_
,
673 class Core_scale3d
: public Lang::CoreFunction
676 Core_scale3d( const char * title
)
677 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
679 Kernel::VariableHandle
one( new Kernel::Variable( RefCountPtr
< const Lang::Value
>( new Lang::Float( 1 ) ) ) );
681 formals_
->appendEvaluatedCoreFormal( "r", one
);
682 formals_
->appendEvaluatedCoreFormal( "x", one
);
683 formals_
->appendEvaluatedCoreFormal( "y", one
);
684 formals_
->appendEvaluatedCoreFormal( "z", one
);
687 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
689 args
.applyDefaults( );
691 typedef const Lang::Float ArgType
;
692 RefCountPtr
< ArgType
> argr
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 0, callLoc
);
693 RefCountPtr
< ArgType
> argx
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 1, callLoc
);
694 RefCountPtr
< ArgType
> argy
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 2, callLoc
);
695 RefCountPtr
< ArgType
> argz
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 3, callLoc
);
697 Kernel::ContRef cont
= evalState
->cont_
;
698 cont
->takeValue( Kernel::ValueRef( new Lang::Transform3D( argr
->val_
* argx
->val_
, 0, 0,
699 0, argr
->val_
* argy
->val_
, 0,
700 0, 0, argr
->val_
* argz
->val_
,
706 class Core_inverse
: public Lang::CoreFunction
709 Core_inverse( const char * title
) : CoreFunction( title
) { }
711 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
713 const size_t ARITY
= 1;
714 CHECK_ARITY( args
, ARITY
, title_
);
717 typedef const Lang::Transform2D ArgType
;
718 ArgType
* tf
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
721 double det
= tf
->xx_
* tf
->yy_
- tf
->xy_
* tf
->yx_
;
722 if( fabs( det
) < Computation::SINGULAR_TRANSFORM_LIMIT
)
724 throw Exceptions::CoreOutOfRange( title_
, args
, 0, "Singular transforms cannot be inverted." );
726 double idet
= 1 / det
;
727 double ixx
= idet
* tf
->yy_
;
728 double ixy
= - idet
* tf
->xy_
;
729 double iyx
= - idet
* tf
->yx_
;
730 double iyy
= idet
* tf
->xx_
;
731 Kernel::ContRef cont
= evalState
->cont_
;
732 cont
->takeValue( Kernel::ValueRef( new Lang::Transform2D( ixx
, iyx
,
734 -( ixx
* tf
->xt_
+ ixy
* tf
->yt_
), -( iyx
* tf
->xt_
+ iyy
* tf
->yt_
) ) ),
741 typedef const Lang::Transform3D ArgType
;
742 ArgType
* tf
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
746 tf
->xx_
* ( tf
->yy_
* tf
->zz_
- tf
->yz_
* tf
->zy_
)
747 - tf
->xy_
* ( tf
->yx_
* tf
->zz_
- tf
->yz_
* tf
->zx_
)
748 + tf
->xz_
* ( tf
->yx_
* tf
->zy_
- tf
->yy_
* tf
->zx_
);
749 if( fabs( det
) < Computation::SINGULAR_TRANSFORM_LIMIT
)
751 throw Exceptions::CoreOutOfRange( title_
, args
, 0, "Singular transforms cannot be inverted." );
753 double idet
= 1 / det
;
754 double ixx
= idet
* ( tf
->yy_
* tf
->zz_
- tf
->yz_
* tf
->zy_
);
755 double ixy
= - idet
* ( tf
->xy_
* tf
->zz_
- tf
->xz_
* tf
->zy_
);
756 double ixz
= idet
* ( tf
->xy_
* tf
->yz_
- tf
->xz_
* tf
->yy_
);
757 double iyx
= - idet
* ( tf
->yx_
* tf
->zz_
- tf
->yz_
* tf
->zx_
);
758 double iyy
= idet
* ( tf
->xx_
* tf
->zz_
- tf
->xz_
* tf
->zx_
);
759 double iyz
= - idet
* ( tf
->xx_
* tf
->yz_
- tf
->xz_
* tf
->yx_
);
760 double izx
= idet
* ( tf
->yx_
* tf
->zy_
- tf
->yy_
* tf
->zx_
);
761 double izy
= - idet
* ( tf
->xx_
* tf
->zy_
- tf
->xy_
* tf
->zx_
);
762 double izz
= idet
* ( tf
->xx_
* tf
->yy_
- tf
->xy_
* tf
->yx_
);
763 Kernel::ContRef cont
= evalState
->cont_
;
764 cont
->takeValue( Kernel::ValueRef( new Lang::Transform3D( ixx
, iyx
, izx
,
767 -( ixx
* tf
->xt_
+ ixy
* tf
->yt_
+ ixz
* tf
->zt_
),
768 -( iyx
* tf
->xt_
+ iyy
* tf
->yt_
+ iyz
* tf
->zt_
),
769 -( izx
* tf
->xt_
+ izy
* tf
->yt_
+ izz
* tf
->zt_
) ) ),
775 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, 0, Helpers::typeSetString( Lang::Transform2D::staticTypeName( ), Lang::Transform3D::staticTypeName( ) ) );
779 class Core_formxo
: public Lang::CoreFunction
782 Core_formxo( const char * title
) : CoreFunction( title
) { }
784 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
786 const size_t ARITY
= 1;
787 CHECK_ARITY( args
, ARITY
, title_
);
789 typedef const Lang::Drawable2D ArgType
;
790 RefCountPtr
< ArgType
> arg
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 0, callLoc
);
792 RefCountPtr
< const Lang::ElementaryPath2D
> theBBox
= arg
->bbox( Lang::Drawable2D::BOUNDING
);
793 Concrete::Coords2D
llcorner( 0, 0 );
794 Concrete::Coords2D
urcorner( 0, 0 );
795 if( ! theBBox
->boundingRectangle( & llcorner
, & urcorner
) )
797 std::string
strTitle( title_
);
798 throw Exceptions::InternalError( strrefdup( strTitle
+ ": The object has no bounding box!" ) );
802 RefCountPtr
< SimplePDF::PDF_Stream_out
> form
;
803 RefCountPtr
< SimplePDF::PDF_Object
> indirection
= SimplePDF::indirect( form
, & Kernel::theIndirectObjectCount
);
805 RefCountPtr
< SimplePDF::PDF_Resources
> resources
;
806 (*form
)[ "Resources" ] = SimplePDF::indirect( resources
, & Kernel::theIndirectObjectCount
);
808 (*form
)[ "Subtype" ] = SimplePDF::newName( "Form" );
809 (*form
)[ "FormType" ] = SimplePDF::newInt( 1 );
810 (*form
)[ "BBox" ] = RefCountPtr
< SimplePDF::PDF_Vector
>( new SimplePDF::PDF_Vector( llcorner
.x_
.offtype
< 1, 0 >( ), llcorner
.y_
.offtype
< 1, 0 >( ),
811 urcorner
.x_
.offtype
< 1, 0 >( ), urcorner
.y_
.offtype
< 1, 0 >( ) ) );
813 /* There's a possibility of adding a transformation matrix entry in the dictionary here, but it is not used, not even
814 * for transformed drawables.
816 // (*markForm)[ "Matrix" ] = RefCountPtr<PDF_Object>( new PDF_Vector( 1, 0, 0, 1, -30, -30 ) );
818 Kernel::PageContentStates
pdfState( resources
);
819 arg
->shipout( form
->data
, & pdfState
, Lang::Transform2D( 1, 0, 0, 1, 0, 0 ) );
822 Lang::XObject
* res
= new Lang::XObject( indirection
,
824 res
->setDebugStr( "user form" );
825 Kernel::ContRef cont
= evalState
->cont_
;
826 cont
->takeValue( Kernel::ValueRef( res
),
831 class Core_transparencygroup
: public Lang::CoreFunction
834 Core_transparencygroup( const char * title
)
835 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
837 formals_
->appendEvaluatedCoreFormal( "content", Kernel::THE_SLOT_VARIABLE
);
838 formals_
->appendEvaluatedCoreFormal( "isolated", Kernel::THE_FALSE_VARIABLE
);
839 formals_
->appendEvaluatedCoreFormal( "knockout", Kernel::THE_FALSE_VARIABLE
);
842 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
844 args
.applyDefaults( );
846 typedef const Lang::Group2D ArgType0
;
847 typedef const Lang::Boolean ArgType1
;
848 typedef const Lang::Boolean ArgType2
;
849 RefCountPtr
< ArgType0
> content
= Helpers::down_cast_CoreArgument
< ArgType0
>( title_
, args
, 0, callLoc
);
850 RefCountPtr
< ArgType1
> isolated
= Helpers::down_cast_CoreArgument
< ArgType1
>( title_
, args
, 1, callLoc
);
851 RefCountPtr
< ArgType2
> knockout
= Helpers::down_cast_CoreArgument
< ArgType2
>( title_
, args
, 2, callLoc
);
853 RefCountPtr
< const Lang::ColorSpace
> blendSpace
= evalState
->dyn_
->getBlendSpace( );
855 Kernel::ContRef cont
= evalState
->cont_
;
856 cont
->takeValue( Helpers::newTransparencyGroup( content
, isolated
->val_
, knockout
->val_
, blendSpace
),
861 class Core_importRasterImage
: public Lang::CoreFunction
863 std::map
< const char *, const Helpers::RasterLoader
*, charPtrLess
> loaders_
;
865 Core_importRasterImage( const char * title
)
866 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
868 formals_
->appendEvaluatedCoreFormal( "filename", Kernel::THE_SLOT_VARIABLE
);
869 formals_
->appendEvaluatedCoreFormal( "resolution", Helpers::newValHandle( new Lang::Length( Concrete::Length( 1 ) ) ) );
870 formals_
->appendEvaluatedCoreFormal( "override", Kernel::THE_TRUE_VARIABLE
);
871 formals_
->appendEvaluatedCoreFormal( "kind", Kernel::THE_VOID_VARIABLE
);
873 loaders_
[ "png" ] = & Helpers::theRasterLoader_PNG
;
874 loaders_
[ "PNG" ] = & Helpers::theRasterLoader_PNG
;
876 loaders_
[ "jpg" ] = & Helpers::theRasterLoader_JPEG
;
877 loaders_
[ "JPG" ] = & Helpers::theRasterLoader_JPEG
;
878 loaders_
[ "jpeg" ] = & Helpers::theRasterLoader_JPEG
;
879 loaders_
[ "JPEG" ] = & Helpers::theRasterLoader_JPEG
;
881 /* It would seem natural to also support "JIF"-images, but currently the JPEG library we use won't open such files.
885 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
887 args
.applyDefaults( );
891 typedef const Lang::String ArgType
;
892 RefCountPtr
< ArgType
> filename
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, argsi
, callLoc
);
893 size_t argsi_filename
= argsi
;
895 std::string full_filename
;
898 full_filename
= Ast::theShapesScanner
.searchFile( filename
->val_
.getPtr( ), true ); /* true means that errors should be handled in "runtime mode". */
900 catch( RefCountPtr
< const char > & msg
)
902 throw Exceptions::CoreOutOfRange( title_
, args
, argsi_filename
, msg
);
905 RefCountPtr
< std::ifstream
> iFile( new std::ifstream( full_filename
.c_str( ) ) );
906 if( ! iFile
->good( ) )
908 std::ostringstream msg
;
909 msg
<< "Failed to open file for input: " << full_filename
.c_str( ) ;
910 throw Exceptions::CoreOutOfRange( title_
, args
, argsi_filename
, strrefdup( msg
) );
914 typedef const Lang::Length ResolutionType
;
915 Concrete::Length resolution
= Helpers::down_cast_CoreArgument
< ResolutionType
>( title_
, args
, argsi
, callLoc
)->get( );
916 if( resolution
<= Concrete::ZERO_LENGTH
)
918 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, strrefdup( "The resolution must be positive." ) );
922 typedef const Lang::Boolean OverrideType
;
923 bool override
= Helpers::down_cast_CoreArgument
< OverrideType
>( title_
, args
, argsi
, callLoc
)->val_
;
926 typedef const Lang::Symbol KindType
;
927 RefCountPtr
< KindType
> kind
= Helpers::down_cast_CoreArgument
< KindType
>( title_
, args
, argsi
, callLoc
, true );
928 const Helpers::RasterLoader
* loader
= 0;
929 if( kind
== NullPtr
< KindType
>( ) )
931 const char * begin
= filename
->val_
.getPtr( );
932 const char * ext
= filename
->val_
.getPtr( ) + filename
->bytecount_
- 1;
933 for( ; ext
> begin
; --ext
)
937 typedef typeof loaders_ MapType
;
938 MapType::const_iterator i
= loaders_
.find( ext
+ 1 );
939 if( i
== loaders_
.end( ) )
941 std::ostringstream msg
;
942 msg
<< "Filename extension '" << ext
<< "' has no associated raster loader." ;
943 throw Exceptions::CoreOutOfRange( title_
, args
, argsi_filename
, strrefdup( msg
) );
951 std::ostringstream msg
;
952 msg
<< "Filename without extension must be combined with explicit file kind: " << filename
->val_
.getPtr( ) ;
953 throw Exceptions::CoreOutOfRange( title_
, args
, argsi_filename
, strrefdup( msg
) );
958 static Lang::Symbol
PNG( "PNG" );
959 static Lang::Symbol
JPEG( "JPEG" );
962 loader
= & Helpers::theRasterLoader_PNG
;
964 else if( *kind
== JPEG
)
966 loader
= & Helpers::theRasterLoader_JPEG
;
970 std::ostringstream msg
;
971 msg
<< "The only allowed file kind symbols are { " ;
976 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, strrefdup( msg
) );
980 Kernel::ContRef cont
= evalState
->cont_
;
981 cont
->takeValue( loader
->load( iFile
, full_filename
, resolution
, override
, title_
, callLoc
),
986 class Core_vector
: public Lang::CoreFunction
989 Core_vector( const char * title
) : CoreFunction( title
) { }
991 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
993 std::vector
< RefCountPtr
< const Lang::Value
> > * res
= new std::vector
< RefCountPtr
< const Lang::Value
> >;
994 res
->reserve( args
.size( ) );
996 for( size_t i
= 0; i
!= args
.size( ); ++i
)
998 res
->push_back( args
.getValue( i
) );
1001 Kernel::ContRef cont
= evalState
->cont_
;
1002 cont
->takeValue( Kernel::ValueRef( new Lang::VectorFunction( res
) ),
1007 class Core_interpolate
: public Lang::CoreFunction
1010 Core_interpolate( const char * title
)
1011 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
1013 formals_
->appendEvaluatedCoreFormal( "function", Kernel::THE_SLOT_VARIABLE
);
1014 formals_
->appendEvaluatedCoreFormal( "domain", Kernel::THE_SLOT_VARIABLE
);
1015 formals_
->appendEvaluatedCoreFormal( "size", Kernel::THE_SLOT_VARIABLE
);
1016 formals_
->appendEvaluatedCoreFormal( "range", Kernel::THE_SLOT_VARIABLE
);
1017 formals_
->appendEvaluatedCoreFormal( "encode", Kernel::THE_VOID_VARIABLE
);
1018 formals_
->appendEvaluatedCoreFormal( "decode", Kernel::THE_VOID_VARIABLE
);
1021 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1023 args
.applyDefaults( );
1025 throw Exceptions::NotImplemented( "Core_interpolate::call" );
1029 class Core_importPDFpages
: public Lang::CoreFunction
1032 Core_importPDFpages( const char * title
) : CoreFunction( title
) { }
1034 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1036 const size_t ARITY
= 1;
1037 CHECK_ARITY( args
, ARITY
, title_
);
1039 typedef const Lang::String ArgType
;
1040 RefCountPtr
< ArgType
> arg
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 0, callLoc
);
1042 std::string filename
;
1045 filename
= Ast::theShapesScanner
.searchFile( arg
->val_
.getPtr( ), true ); /* true means that errors should be handled in "runtime mode". */
1047 catch( RefCountPtr
< const char > & msg
)
1049 throw Exceptions::CoreOutOfRange( title_
, args
, 0, msg
);
1052 RefCountPtr
< std::ifstream
> iFile( new std::ifstream( filename
.c_str( ) ) );
1053 if( ! iFile
->good( ) )
1055 std::ostringstream msg
;
1056 msg
<< "Failed to open file for input: " << arg
->val_
.getPtr( ) ;
1057 throw Exceptions::CoreOutOfRange( title_
, args
, 0, strrefdup( msg
) );
1059 RefCountPtr
< SimplePDF::PDF_in
> pdfi( new SimplePDF::PDF_in( iFile
) );
1061 RefCountPtr
< const std::vector
< RefCountPtr
< const Lang::XObject
> > > typedRes
= RefCountPtr
< const std::vector
< RefCountPtr
< const Lang::XObject
> > >( NullPtr
< std::vector
< RefCountPtr
< const Lang::XObject
> > >( ) );
1064 typedRes
= Kernel::thePDFImporter
.addPagesAsXObjects( pdfi
);
1066 catch( const char * ball
)
1068 throw Exceptions::InternalError( strrefdup( ( std::string( "An error occurred while importing " ) + arg
->val_
.getPtr( ) + ": " + ball
).c_str( ) ) );
1071 std::vector
< RefCountPtr
< const Lang::Value
> > * untypedRes
= new std::vector
< RefCountPtr
< const Lang::Value
> >;
1072 untypedRes
->reserve( typedRes
->size( ) );
1073 typedef typeof *typedRes ListType
;
1074 for( ListType::const_iterator i
= typedRes
->begin( ); i
!= typedRes
->end( ); ++i
)
1076 untypedRes
->push_back( *i
);
1079 Kernel::ContRef cont
= evalState
->cont_
;
1080 cont
->takeValue( Kernel::ValueRef( new Lang::VectorFunction( untypedRes
) ),
1085 namespace Implementation
1088 svg_path_strtod( const char ** src
)
1090 const char * start
= *src
;
1092 double res
= strtod( start
, & endp
);
1096 for( ; *start
== ' '; ++start
)
1098 throw std::string( start
, strchr( start
, ' ' ) - start
);
1103 class Core_svg_path
: public Lang::CoreFunction
1106 Core_svg_path( const char * title
)
1107 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
1109 formals_
->appendEvaluatedCoreFormal( "d", Kernel::THE_SLOT_VARIABLE
);
1110 formals_
->appendEvaluatedCoreFormal( "xunit", Helpers::newValHandle( new Lang::Length( Concrete::Length( 1 ) ) ) );
1111 formals_
->appendEvaluatedCoreFormal( "yunit", Helpers::newValHandle( new Lang::Length( Concrete::Length( 1 ) ) ) );
1112 formals_
->appendEvaluatedCoreFormal( "multi", Kernel::THE_VOID_VARIABLE
);
1113 formals_
->appendEvaluatedCoreFormal( "singletons", Kernel::THE_TRUE_VARIABLE
);
1116 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1118 args
.applyDefaults( );
1121 typedef const Lang::String StrType
;
1122 RefCountPtr
< StrType
> arg
= Helpers::down_cast_CoreArgument
< StrType
>( title_
, args
, argsi
, callLoc
);
1124 typedef const Lang::Length ScaleType
;
1126 Concrete::Length dx
= Helpers::down_cast_CoreArgument
< ScaleType
>( title_
, args
, argsi
, callLoc
)->get( );
1128 Concrete::Length dy
= Helpers::down_cast_CoreArgument
< ScaleType
>( title_
, args
, argsi
, callLoc
)->get( );
1130 typedef const Lang::Boolean FlagType
;
1132 RefCountPtr
< FlagType
> multi
= Helpers::down_cast_CoreArgument
< FlagType
>( title_
, args
, argsi
, callLoc
, true );
1134 bool singletons
= Helpers::down_cast_CoreArgument
< FlagType
>( title_
, args
, argsi
, callLoc
)->val_
;
1136 RefCountPtr
< char > buf
= RefCountPtr
< char >( new char[ 2 * strlen( arg
->val_
.getPtr( ) + 1 ) ] );
1138 /* Get rid of any whitespace that isn't a plain space, and make sure every number is terminated by whitespace.
1140 char * dst
= buf
.getPtr( );
1141 for( const char * src
= arg
->val_
.getPtr( ); *src
!= '\0'; ++src
, ++dst
)
1151 if( ( 'A' <= *src
&& *src
<= 'Z' ) || ( 'a' <= *src
&& *src
<= 'z' ) )
1153 /* Insert whitespace before command to ensure command is not immediately following number.
1165 RefCountPtr
< Lang::MultiPath2D
> multiPath
= RefCountPtr
< Lang::MultiPath2D
>( new Lang::MultiPath2D
);
1166 RefCountPtr
< Lang::ElementaryPath2D
> elemPath
= RefCountPtr
< Lang::ElementaryPath2D
>( NullPtr
< Lang::ElementaryPath2D
>( ) );
1171 Concrete::PathPoint2D
originPathPoint( new Concrete::Coords2D( 0, 0 ) );
1172 Concrete::PathPoint2D
* first
= & originPathPoint
;
1173 Concrete::PathPoint2D
* last
= & originPathPoint
;
1174 const char * srcEnd
= buf
.getPtr( ) + strlen( buf
.getPtr( ) );
1175 for( const char * src
= buf
.getPtr( ); src
< srcEnd
; ++src
)
1177 for( ; *src
== ' '; ++src
)
1211 throw Exceptions::CoreOutOfRange( title_
, args
, 0, strrefdup( std::string( "SVG path command not compatible with cubic splines: " ) + *src
) );
1218 if( elemPath
!= NullPtr
< Lang::ElementaryPath2D
>( ) && ( singletons
|| elemPath
->duration( ) >= 1 ) )
1220 multiPath
->push_back( elemPath
);
1222 Concrete::Length x
= dx
* Implementation::svg_path_strtod( & src
);
1223 Concrete::Length y
= - dy
* Implementation::svg_path_strtod( & src
);
1224 first
= new Concrete::PathPoint2D( new Concrete::Coords2D( x
, y
) );
1226 elemPath
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D
);
1227 elemPath
->push_back( last
);
1233 if( elemPath
!= NullPtr
< Lang::ElementaryPath2D
>( ) && ( singletons
|| elemPath
->duration( ) >= 1 ) )
1235 multiPath
->push_back( elemPath
);
1237 Concrete::Length x
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1238 Concrete::Length y
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1239 first
= new Concrete::PathPoint2D( new Concrete::Coords2D( x
, y
) );
1241 elemPath
= RefCountPtr
< Lang::ElementaryPath2D
>( new Lang::ElementaryPath2D
);
1242 elemPath
->push_back( last
);
1260 Concrete::Length x
= dx
* Implementation::svg_path_strtod( & src
);
1261 Concrete::Length y
= - dy
* Implementation::svg_path_strtod( & src
);
1262 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x
, y
) );
1263 elemPath
->push_back( last
);
1268 Concrete::Length x
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1269 Concrete::Length y
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1270 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x
, y
) );
1271 elemPath
->push_back( last
);
1276 Concrete::Length x
= dx
* Implementation::svg_path_strtod( & src
);
1277 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x
, last
->mid_
->y_
) );
1278 elemPath
->push_back( last
);
1283 Concrete::Length x
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1284 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x
, last
->mid_
->y_
) );
1285 elemPath
->push_back( last
);
1290 Concrete::Length y
= - dy
* Implementation::svg_path_strtod( & src
);
1291 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( last
->mid_
->x_
, y
) );
1292 elemPath
->push_back( last
);
1297 Concrete::Length y
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1298 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( last
->mid_
->x_
, y
) );
1299 elemPath
->push_back( last
);
1304 Concrete::Length x1
= dx
* Implementation::svg_path_strtod( & src
);
1305 Concrete::Length y1
= - dy
* Implementation::svg_path_strtod( & src
);
1306 Concrete::Length x2
= dx
* Implementation::svg_path_strtod( & src
);
1307 Concrete::Length y2
= - dy
* Implementation::svg_path_strtod( & src
);
1308 Concrete::Length x3
= dx
* Implementation::svg_path_strtod( & src
);
1309 Concrete::Length y3
= - dy
* Implementation::svg_path_strtod( & src
);
1310 last
->front_
= new Concrete::Coords2D( x1
, y1
);
1311 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x3
, y3
) );
1312 last
->rear_
= new Concrete::Coords2D( x2
, y2
);
1313 elemPath
->push_back( last
);
1318 Concrete::Length x1
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1319 Concrete::Length y1
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1320 Concrete::Length x2
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1321 Concrete::Length y2
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1322 Concrete::Length x3
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1323 Concrete::Length y3
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1324 last
->front_
= new Concrete::Coords2D( x1
, y1
);
1325 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x3
, y3
) );
1326 last
->rear_
= new Concrete::Coords2D( x2
, y2
);
1327 elemPath
->push_back( last
);
1332 Concrete::Length x2
= dx
* Implementation::svg_path_strtod( & src
);
1333 Concrete::Length y2
= - dy
* Implementation::svg_path_strtod( & src
);
1334 Concrete::Length x3
= dx
* Implementation::svg_path_strtod( & src
);
1335 Concrete::Length y3
= - dy
* Implementation::svg_path_strtod( & src
);
1336 last
->front_
= new Concrete::Coords2D( 2 * *(last
->mid_
) - *(last
->rear_
) );
1337 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x3
, y3
) );
1338 last
->rear_
= new Concrete::Coords2D( x2
, y2
);
1339 elemPath
->push_back( last
);
1344 Concrete::Length x2
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1345 Concrete::Length y2
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1346 Concrete::Length x3
= last
->mid_
->x_
+ dx
* Implementation::svg_path_strtod( & src
);
1347 Concrete::Length y3
= last
->mid_
->y_
- dy
* Implementation::svg_path_strtod( & src
);
1348 last
->front_
= new Concrete::Coords2D( 2 * *(last
->mid_
) - *(last
->rear_
) );
1349 last
= new Concrete::PathPoint2D( new Concrete::Coords2D( x3
, y3
) );
1350 last
->rear_
= new Concrete::Coords2D( x2
, y2
);
1351 elemPath
->push_back( last
);
1355 throw Exceptions::CoreOutOfRange( title_
, args
, 0, "Malformed SVG path string (failed to initialize command character)." );
1358 throw Exceptions::InternalError( "While reading SVG path string: Command character out of range." );
1363 catch( const std::string
& badNumber
)
1365 throw Exceptions::CoreOutOfRange( title_
, args
, 0, strrefdup( std::string( "Ill-formed number: " ) + badNumber
) );
1368 if( elemPath
!= NullPtr
< Lang::ElementaryPath2D
>( ) && ( singletons
|| elemPath
->duration( ) >= 1 ) )
1370 multiPath
->push_back( RefCountPtr
< const Lang::Path2D
>( elemPath
) );
1373 if( multiPath
->size( ) == 0 )
1375 throw Exceptions::CoreOutOfRange( title_
, args
, 0, "No path was produced." );
1377 if( multiPath
->size( ) == 1 )
1379 Kernel::ContRef cont
= evalState
->cont_
;
1380 if( multi
!= NullPtr
< FlagType
>( ) && multi
->val_
)
1382 cont
->takeValue( Kernel::ValueRef( multiPath
),
1387 cont
->takeValue( Kernel::ValueRef( multiPath
->front( ) ),
1393 if( multi
!= NullPtr
< FlagType
>( ) && ! multi
->val_
)
1395 throw Exceptions::CoreOutOfRange( title_
, args
, 0, "More than one sub-path conflicts with false for <multi>." );
1397 Kernel::ContRef cont
= evalState
->cont_
;
1398 cont
->takeValue( Kernel::ValueRef( multiPath
),
1404 class Core_sprintf
: public Lang::CoreFunction
1407 Core_sprintf( const char * title
) : CoreFunction( title
) { }
1409 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1413 throw Exceptions::CoreArityMismatch( title_
, 1, args
.size( ) );
1415 typedef typeof args ArgListType
;
1417 typedef const Lang::String Arg1Type
;
1418 RefCountPtr
< Arg1Type
> arg1
= Helpers::down_cast_CoreArgument
< Arg1Type
>( title_
, args
, i
, callLoc
);
1420 /* snprintf( 0, 0, ... ) does not seem to work properly on some systems.
1421 * Therefore, I resort to the use of a dummy string, and "n = 1".
1426 switch( args
.size( ) )
1430 size_t sz
= snprintf( dummy
, 1, arg1
->val_
.getPtr( ), 0 ); /* The final 0 is just a dummy argument that makes the compiler relax. */
1431 res
= new char[ sz
+ 1 ];
1432 status
= sprintf( res
, arg1
->val_
.getPtr( ), 0 ); /* The final 0 is just a dummy argument that makes the compiler relax. */
1439 typedef const Lang::String Arg2Type
;
1440 Arg2Type
* arg2
= dynamic_cast< Arg2Type
* >( args
.getValue( i
).getPtr( ) );
1443 size_t sz
= snprintf( dummy
, 1, arg1
->val_
.getPtr( ), arg2
->val_
.getPtr( ) );
1444 res
= new char[ sz
+ 1 ];
1445 status
= sprintf( res
, arg1
->val_
.getPtr( ), arg2
->val_
.getPtr( ) );
1450 typedef const Lang::Float Arg2Type
;
1451 Arg2Type
* arg2
= dynamic_cast< Arg2Type
* >( args
.getValue( i
).getPtr( ) );
1454 size_t sz
= snprintf( dummy
, 1, arg1
->val_
.getPtr( ), arg2
->val_
);
1455 res
= new char[ sz
+ 1 ];
1456 status
= sprintf( res
, arg1
->val_
.getPtr( ), arg2
->val_
);
1461 typedef const Lang::Integer Arg2Type
;
1462 Arg2Type
* arg2
= dynamic_cast< Arg2Type
* >( args
.getValue( i
).getPtr( ) );
1465 size_t sz
= snprintf( dummy
, 1, arg1
->val_
.getPtr( ), arg2
->val_
);
1466 res
= new char[ sz
+ 1 ];
1467 status
= sprintf( res
, arg1
->val_
.getPtr( ), arg2
->val_
);
1472 typedef const Lang::ChronologicalTime Arg2Type
;
1473 Arg2Type
* arg2
= dynamic_cast< Arg2Type
* >( args
.getValue( i
).getPtr( ) );
1476 const char * fmt
= arg1
->val_
.getPtr( );
1477 const struct tm
* tmp
= arg2
->temporary_localtime( );
1478 size_t sz
= strlen( fmt
) * 2;
1479 res
= new char[ sz
];
1480 while( strftime( res
, sz
, fmt
, tmp
) == 0 )
1484 res
= new char[ sz
];
1486 status
= 0; // Here, I'd like to check some error condition instead...
1490 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, i
, Interaction::SEVERAL_TYPES
);
1494 throw Exceptions::CoreOutOfRange( title_
, args
, 0, "The number of arguments is out of the implemented range." );
1499 throw Exceptions::InternalError( "Failed to assign to res in sprintf." );
1504 std::ostringstream oss
;
1505 oss
<< "Call to library routine returned negative value indicating an error: " << status
<< ".";
1506 throw Exceptions::CoreOutOfRange( title_
, args
, 0, strrefdup( oss
) );
1509 Kernel::ContRef cont
= evalState
->cont_
;
1510 cont
->takeValue( Kernel::ValueRef( new Lang::String( res
, false ) ),
1515 class Core_strftime
: public Lang::CoreFunction
1518 Core_strftime( const char * title
) : CoreFunction( title
) { }
1520 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1522 const size_t ARITY
= 0;
1523 CHECK_ARITY( args
, ARITY
, title_
);
1528 timeInfo
= localtime( & t
);
1529 std::ostringstream res
;
1530 res
<< timeInfo
->tm_hour
<< ":" << timeInfo
->tm_min
<< ":" << timeInfo
->tm_sec
;
1532 Kernel::ContRef cont
= evalState
->cont_
;
1533 cont
->takeValue( Kernel::ValueRef( new Lang::String( strrefdup( res
) ) ),
1538 class Core_ambient_light
: public Lang::CoreFunction
1541 Core_ambient_light( const char * title
)
1542 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
1544 formals_
->appendEvaluatedCoreFormal( "color", Kernel::THE_SLOT_VARIABLE
);
1547 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1549 args
.applyDefaults( );
1552 typedef const Lang::Gray ArgType
;
1553 ArgType
* col
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
1556 Kernel::ContRef cont
= evalState
->cont_
;
1557 cont
->takeValue( Kernel::ValueRef( new Lang::AmbientLightGray( col
->components( ) ) ),
1564 typedef const Lang::RGB ArgType
;
1565 ArgType
* col
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
1568 Kernel::ContRef cont
= evalState
->cont_
;
1569 cont
->takeValue( Kernel::ValueRef( new Lang::AmbientLightRGB( col
->components( ) ) ),
1575 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, 0, Helpers::typeSetString( Lang::Gray::staticTypeName( ), Lang::RGB::staticTypeName( ) ) );
1579 class Core_specular_light
: public Lang::CoreFunction
1582 Core_specular_light( const char * title
)
1583 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
1585 formals_
->appendEvaluatedCoreFormal( "color", Kernel::THE_SLOT_VARIABLE
);
1586 formals_
->appendEvaluatedCoreFormal( "radius", Helpers::newValHandle( new Lang::Length( HUGE_VAL
) ) );
1587 formals_
->appendEvaluatedCoreFormal( "shadows", Kernel::THE_FALSE_VARIABLE
);
1590 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1592 args
.applyDefaults( );
1594 typedef const Lang::Length RadiusType
;
1595 RefCountPtr
< RadiusType
> radius
= Helpers::down_cast_CoreArgument
< RadiusType
>( title_
, args
, 1, callLoc
);
1596 typedef const Lang::Boolean ShadowsType
;
1597 RefCountPtr
< ShadowsType
> shadows
= Helpers::down_cast_CoreArgument
< ShadowsType
>( title_
, args
, 2, callLoc
);
1600 typedef const Lang::Gray ArgType
;
1601 ArgType
* col
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
1604 Kernel::ContRef cont
= evalState
->cont_
;
1605 cont
->takeValue( Kernel::ValueRef( new Lang::SpecularLightGray( Concrete::Coords3D( 0, 0, 0 ),
1615 typedef const Lang::RGB ArgType
;
1616 ArgType
* col
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
1619 Kernel::ContRef cont
= evalState
->cont_
;
1620 cont
->takeValue( Kernel::ValueRef( new Lang::SpecularLightRGB( Concrete::Coords3D( 0, 0, 0 ),
1629 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, 0, Helpers::typeSetString( Lang::Gray::staticTypeName( ), Lang::RGB::staticTypeName( ) ) );
1633 class Core_distant_light
: public Lang::CoreFunction
1636 Core_distant_light( const char * title
)
1637 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
1639 formals_
->appendEvaluatedCoreFormal( "color", Kernel::THE_SLOT_VARIABLE
);
1640 formals_
->appendEvaluatedCoreFormal( "shadows", Kernel::THE_FALSE_VARIABLE
);
1643 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1645 args
.applyDefaults( );
1647 typedef const Lang::Boolean ShadowsType
;
1648 RefCountPtr
< ShadowsType
> shadows
= Helpers::down_cast_CoreArgument
< ShadowsType
>( title_
, args
, 1, callLoc
);
1651 typedef const Lang::Gray ArgType
;
1652 ArgType
* col
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
1655 Kernel::ContRef cont
= evalState
->cont_
;
1656 cont
->takeValue( Kernel::ValueRef( new Lang::DistantLightGray( Concrete::UnitFloatTriple( 0., 0., -1. ),
1665 typedef const Lang::RGB ArgType
;
1666 ArgType
* col
= dynamic_cast< ArgType
* >( args
.getValue( 0 ).getPtr( ) );
1669 Kernel::ContRef cont
= evalState
->cont_
;
1670 cont
->takeValue( Kernel::ValueRef( new Lang::DistantLightRGB( Concrete::UnitFloatTriple( 0., 0., -1. ),
1678 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, 0, Helpers::typeSetString( Lang::Gray::staticTypeName( ), Lang::RGB::staticTypeName( ) ) );
1682 class Core_textrenderingmode
: public Lang::CoreFunction
1685 Core_textrenderingmode( const char * title
)
1686 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
1688 formals_
->appendEvaluatedCoreFormal( "fill", Kernel::THE_FALSE_VARIABLE
);
1689 formals_
->appendEvaluatedCoreFormal( "stroke", Kernel::THE_FALSE_VARIABLE
);
1692 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1694 args
.applyDefaults( );
1696 typedef const Lang::Boolean FlagType
;
1697 RefCountPtr
< FlagType
> fill
= Helpers::down_cast_CoreArgument
< FlagType
>( title_
, args
, 0, callLoc
);
1698 RefCountPtr
< FlagType
> stroke
= Helpers::down_cast_CoreArgument
< FlagType
>( title_
, args
, 1, callLoc
);
1700 Kernel::ContRef cont
= evalState
->cont_
;
1701 cont
->takeValue( Kernel::ValueRef( new Lang::TextRenderingMode( fill
->val_
, stroke
->val_
, false ) ),
1706 class Core_manualkern
: public Lang::CoreFunction
1709 Core_manualkern( const char * title
) : CoreFunction( title
) { }
1711 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1713 // 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
1714 // the result is not used.
1715 RefCountPtr
< Lang::KernedText
> res( new Lang::KernedText( evalState
->dyn_
->getTextState( ), evalState
->dyn_
->getGraphicsState( ) ) );
1717 for( size_t i
= 0; i
!= args
.size( ); ++i
)
1721 typedef const Lang::String ArgType
;
1722 res
->pushString( Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( i
) ) );
1725 catch( const NonLocalExit::NotThisType
& ball
)
1727 // Never mind, see below
1732 typedef const Lang::Float ArgType
;
1733 res
->pushKerning( Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( i
) )->val_
);
1736 catch( const NonLocalExit::NotThisType
& ball
)
1738 // Never mind, see below
1743 typedef const Lang::KernedText ArgType
;
1744 Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( i
) )->push( res
.getPtr( ) );
1747 catch( const NonLocalExit::NotThisType
& ball
)
1749 // Never mind, see below
1752 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, i
, Helpers::typeSetString( Lang::String::staticTypeName( ), Lang::Float::staticTypeName( ), Lang::KernedText::staticTypeName( ) ) );
1755 Kernel::ContRef cont
= evalState
->cont_
;
1756 cont
->takeValue( res
,
1761 class Core_automatickern
: public Lang::CoreFunction
1764 Core_automatickern( const char * title
) : CoreFunction( title
) { }
1766 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1768 iconv_t converter
= Helpers::requireUTF8ToUCS4Converter( );
1769 iconv_t backconverter
= Helpers::requireUCS4ToUTF8Converter( );
1771 RefCountPtr
< const FontMetrics::FontMetric
> metrics
= evalState
->dyn_
->getTextState( )->font_
->metrics( );
1772 if( metrics
->horizontalMetrics_
== NullPtr
< FontMetrics::WritingDirectionMetrics
>( ) )
1774 throw Exceptions::FontMetricsError( evalState
->dyn_
->getTextState( )->font_
->fontName( ), strrefdup( "No horizontal metrics defined." ) );
1777 // 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
1778 // the result is not used.
1779 RefCountPtr
< Lang::KernedText
> res( new Lang::KernedText( evalState
->dyn_
->getTextState( ), evalState
->dyn_
->getGraphicsState( ) ) );
1781 std::ostringstream pendingChars
;
1782 Kernel::UnicodeCodePoint
prevChar( 0 );
1783 double pendingKerning
= 0;
1785 const size_t backbufSize
= 5;
1786 char backbuf
[ backbufSize
];
1788 for( size_t i
= 0; i
!= args
.size( ); ++i
)
1792 typedef const Lang::String ArgType
;
1793 RefCountPtr
< ArgType
> str
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( i
) );
1795 const char * inbuf
= str
->val_
.getPtr( );
1796 size_t inbytesleft
= strlen( inbuf
);
1798 size_t bufSize
= 4 * inbytesleft
;
1799 char * buf
= new char[ bufSize
];
1800 DeleteOnExit
< char > bufDeleter( buf
);
1802 char * outbuf
= buf
;
1803 size_t outbytesleft
= bufSize
;
1804 // The ICONV_CAST macro is defined in config.h.
1805 size_t count
= iconv( converter
,
1806 ICONV_CAST( & inbuf
), & inbytesleft
,
1807 & outbuf
, & outbytesleft
);
1808 if( count
== (size_t)(-1) )
1810 if( errno
== EILSEQ
)
1812 throw Exceptions::MiscellaneousRequirement( "It is suspected that one of the UFT-8 characters used in showed text has no UCS-4 representation." );
1814 else if( errno
== EINVAL
)
1816 throw Exceptions::MiscellaneousRequirement( "It is suspected that showed text ended with an incomplete multibyte character." );
1818 else if( errno
== E2BIG
)
1820 throw Exceptions::InternalError( "Core_automatickern: The buffer allocated for UTF-8 to UCS-4 conversion was too small." );
1824 std::ostringstream msg
;
1825 msg
<< "iconv failed with an unrecognized error code: " << errno
;
1826 throw Exceptions::InternalError( strrefdup( msg
) );
1829 for( const char * src
= buf
; src
!= outbuf
; src
+= 4 )
1831 Kernel::UnicodeCodePoint currentChar
;
1832 currentChar
.decode_UCS4( src
);
1833 double currentKerning
= pendingKerning
- metrics
->getHorizontalKernPairXByCode( prevChar
, currentChar
);
1834 prevChar
= currentChar
;
1836 if( currentKerning
!= 0 )
1838 if( ! pendingChars
.str( ).empty( ) )
1840 res
->pushString( RefCountPtr
< const Lang::String
>( new Lang::String( strrefdup( pendingChars
) ) ) );
1841 pendingChars
.str( "" );
1843 res
->pushKerning( currentKerning
);
1846 // Copy the current (multibyte) character to the character queue
1848 const char * inbuf
= src
;
1849 char * outbuf
= backbuf
;
1850 size_t inbytesleft
= 4;
1851 size_t outbytesleft
= backbufSize
;
1852 // The ICONV_CAST macro is defined in config.h.
1853 size_t count
= iconv( backconverter
,
1854 ICONV_CAST( & inbuf
), & inbytesleft
,
1855 & outbuf
, & outbytesleft
);
1856 if( count
== (size_t)(-1) )
1858 if( errno
== EILSEQ
)
1860 throw Exceptions::ExternalError( "A character converted from UTF-8 could not be converted back to UFT-8." );
1862 else if( errno
== EINVAL
)
1864 throw Exceptions::ExternalError( "A character converted from UTF-8 was deemed incomplete." );
1866 else if( errno
== E2BIG
)
1868 throw Exceptions::InternalError( "The buffer allocated for conversion of a single character back to UTF-8 was too small." );
1872 std::ostringstream msg
;
1873 msg
<< "iconv failed with an unrecognized error code: " << errno
;
1874 throw Exceptions::InternalError( strrefdup( msg
) );
1878 pendingChars
<< backbuf
;
1883 catch( const NonLocalExit::NotThisType
& ball
)
1885 // Never mind, see below
1890 typedef const Lang::Float ArgType
;
1891 pendingKerning
+= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( i
) )->val_
;
1894 catch( const NonLocalExit::NotThisType
& ball
)
1896 // Never mind, see below
1899 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, i
, Helpers::typeSetString( Lang::String::staticTypeName( ), Lang::Float::staticTypeName( ) ) );
1902 if( ! pendingChars
.str( ).empty( ) )
1904 res
->pushString( RefCountPtr
< const Lang::String
>( new Lang::String( strrefdup( pendingChars
) ) ) );
1905 pendingChars
.str( "" );
1908 Kernel::ContRef cont
= evalState
->cont_
;
1909 cont
->takeValue( res
,
1914 class Core_newrandom
: public Lang::CoreFunction
1917 Core_newrandom( const char * title
)
1918 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
1920 formals_
->appendEvaluatedCoreFormal( "seed", Kernel::THE_SLOT_VARIABLE
);
1921 formals_
->appendEvaluatedCoreFormal( "size", Helpers::newValHandle( new Lang::Integer( 32 ) ) );
1924 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1926 args
.applyDefaults( );
1928 typedef const Lang::Integer SizeType
;
1929 Lang::Integer::ValueType sz
= Helpers::down_cast_CoreArgument
< SizeType
>( title_
, args
, 1, callLoc
)->val_
;
1932 throw Exceptions::CoreOutOfRange( title_
, args
, 1, "The size must be at least 8." );
1936 throw Exceptions::CoreOutOfRange( title_
, args
, 1, "The size must at most 256." );
1943 typedef const Lang::ChronologicalTime SeedType
;
1945 RefCountPtr
< SeedType
> seed
= Helpers::try_cast_CoreArgument
< SeedType
>( args
.getValue( argsi
) );
1947 Kernel::ContRef cont
= evalState
->cont_
;
1948 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::HotRandomSeed( sz
, seed
->val( ) ) ),
1952 catch( const NonLocalExit::NotThisType
& ball
)
1954 // Never mind, see below
1959 typedef const Lang::Integer SeedType
;
1961 RefCountPtr
< SeedType
> seed
= Helpers::try_cast_CoreArgument
< SeedType
>( args
.getValue( argsi
) );
1963 Kernel::ContRef cont
= evalState
->cont_
;
1964 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::HotRandomSeed( sz
, seed
->val_
) ),
1968 catch( const NonLocalExit::NotThisType
& ball
)
1970 // Never mind, see below
1973 throw Exceptions::CoreTypeMismatch( callLoc
, title_
, args
, argsi
, Helpers::typeSetString( Lang::Integer::staticTypeName( ), Lang::ChronologicalTime::staticTypeName( ) ) );
1977 class Core_devrandom
: public Lang::CoreFunction
1980 Core_devrandom( const char * title
)
1981 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
1983 formals_
->appendCoreStateFormal( "device" );
1984 formals_
->appendEvaluatedCoreFormal( "size", Helpers::newValHandle( new Lang::Integer( 32 ) ) );
1987 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1989 args
.applyDefaults( );
1991 typedef const Lang::Integer SizeType
;
1992 Lang::Integer::ValueType sz
= Helpers::down_cast_CoreArgument
< SizeType
>( title_
, args
, 0, callLoc
)->val_
;
1995 throw Exceptions::CoreOutOfRange( title_
, args
, 0, "The size must be at least 8." );
1999 throw Exceptions::CoreOutOfRange( title_
, args
, 0, "The size must at most 256." );
2002 typedef Kernel::WarmRandomDevice GeneratorType
;
2003 GeneratorType
* gen
= Helpers::down_cast_CoreState
< GeneratorType
>( title_
, args
, 0, callLoc
);
2005 Kernel::ContRef cont
= evalState
->cont_
;
2006 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::HotRandomSeed( static_cast< size_t >( sz
), gen
) ),
2011 class Core_destination
: public Lang::CoreFunction
2014 Core_destination( const char * title
)
2015 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
2017 formals_
->appendEvaluatedCoreFormal( "remote", Kernel::THE_FALSE_VARIABLE
);
2018 formals_
->appendEvaluatedCoreFormal( "name", Kernel::THE_VOID_VARIABLE
);
2019 formals_
->appendEvaluatedCoreFormal( "level", Kernel::THE_VOID_VARIABLE
);
2020 formals_
->appendEvaluatedCoreFormal( "text", Kernel::THE_VOID_VARIABLE
);
2021 formals_
->appendEvaluatedCoreFormal( "open", Kernel::THE_FALSE_VARIABLE
);
2022 formals_
->appendEvaluatedCoreFormal( "bold", Kernel::THE_FALSE_VARIABLE
);
2023 formals_
->appendEvaluatedCoreFormal( "italic", Kernel::THE_FALSE_VARIABLE
);
2024 formals_
->appendEvaluatedCoreFormal( "color", Helpers::newValHandle( new Lang::RGB( Concrete::RGB( 0, 0, 0 ) ) ) );
2025 formals_
->appendEvaluatedCoreFormal( "sides", Kernel::THE_VOID_VARIABLE
);
2026 formals_
->appendEvaluatedCoreFormal( "target", Kernel::THE_VOID_VARIABLE
);
2027 formals_
->appendEvaluatedCoreFormal( "fittobbox", Kernel::THE_VOID_VARIABLE
);
2028 formals_
->appendEvaluatedCoreFormal( "zoom", Kernel::THE_VOID_VARIABLE
);
2029 formals_
->appendEvaluatedCoreFormal( "transform", Kernel::THE_TRUE_VARIABLE
);
2032 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2034 args
.applyDefaults( );
2037 const size_t remove_i
= argsi
;
2038 typedef const Lang::Boolean RemoteType
;
2039 bool remote
= Helpers::down_cast_CoreArgument
< RemoteType
>( title_
, args
, argsi
, callLoc
)->val_
;
2042 typedef const Lang::String NameType
;
2043 RefCountPtr
< NameType
> nameVal
= Helpers::down_cast_CoreArgument
< NameType
>( title_
, args
, argsi
, callLoc
, true );
2044 RefCountPtr
< const char > name
= RefCountPtr
< const char >( NullPtr
< const char >( ) );
2045 if( nameVal
!= NullPtr
< NameType
>( ) )
2047 const SimplePDF::PDF_Version::Version STRINGDESTS_VERSION
= SimplePDF::PDF_Version::PDF_1_2
;
2048 if( Kernel::the_PDF_version
.greaterOrEqual( STRINGDESTS_VERSION
) )
2050 name
= nameVal
->val_
;
2054 Kernel::the_PDF_version
.message( STRINGDESTS_VERSION
, "The naming of a destination was ignored." );
2055 // Note that this will leave name being null, and hence generate further errors if remote_.
2058 if( nameVal
== NullPtr
< NameType
>( ) ) // Note why this is not an else clause!
2062 throw Exceptions::CoreOutOfRange( title_
, args
, remove_i
, "The destination cannot be remote if no name is given." );
2067 const size_t outlineLevel_i
= argsi
;
2068 typedef const Lang::Integer OutlineLevelType
;
2069 RefCountPtr
< OutlineLevelType
> levelVal
= Helpers::down_cast_CoreArgument
< OutlineLevelType
>( title_
, args
, argsi
, callLoc
, true );
2070 int outlineLevel
= -1; // This will remain negative only if the level is not present.
2071 if( levelVal
!= NullPtr
< OutlineLevelType
>( ) )
2073 outlineLevel
= levelVal
->val_
;
2074 if( outlineLevel
< 0 )
2076 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "The outline level must be non-negative." );
2081 typedef const Lang::String OutlineTextType
;
2082 RefCountPtr
< OutlineTextType
> textVal
= Helpers::down_cast_CoreArgument
< OutlineTextType
>( title_
, args
, argsi
, callLoc
, true );
2083 RefCountPtr
< const char > outlineText
= RefCountPtr
< const char >( NullPtr
< const char >( ) );
2084 if( textVal
!= NullPtr
< OutlineTextType
>( ) )
2086 outlineText
= textVal
->val_
;
2090 if( outlineLevel
>= 0 )
2092 throw Exceptions::CoreOutOfRange( title_
, args
, outlineLevel_i
, "Without an outline text, it is not allowed to make an outline item." );
2097 typedef const Lang::Boolean OutlineOpenType
;
2098 bool outlineOpen
= Helpers::down_cast_CoreArgument
< OutlineOpenType
>( title_
, args
, argsi
, callLoc
)->val_
;
2101 typedef const Lang::Boolean OutlineBoldType
;
2102 bool outlineBold
= Helpers::down_cast_CoreArgument
< OutlineBoldType
>( title_
, args
, argsi
, callLoc
)->val_
;
2105 typedef const Lang::Boolean OutlineItalicType
;
2106 bool outlineItalic
= Helpers::down_cast_CoreArgument
< OutlineItalicType
>( title_
, args
, argsi
, callLoc
)->val_
;
2109 typedef const Lang::RGB OutlineColorType
;
2110 Concrete::RGB outlineColor
= Helpers::down_cast_CoreArgument
< OutlineColorType
>( title_
, args
, argsi
, callLoc
)->components( );
2113 const size_t sidesMode_i
= argsi
;
2114 typedef const Lang::Symbol SidesModeType
;
2115 RefCountPtr
< SidesModeType
> sidesVal
= Helpers::down_cast_CoreArgument
< SidesModeType
>( title_
, args
, argsi
, callLoc
, true );
2118 const size_t target_i
= argsi
;
2119 typedef const Lang::Drawable2D TargetType
;
2120 RefCountPtr
< TargetType
> target
= Helpers::down_cast_CoreArgument
< TargetType
>( title_
, args
, argsi
, callLoc
, true );
2122 Lang::DocumentDestination::Sides sides
= Lang::DocumentDestination::PAGE
; // Defaults to false, unless a target is given.
2123 if( target
!= NullPtr
< TargetType
>( ) )
2125 sides
= Lang::DocumentDestination::TOPLEFT
;
2128 throw Exceptions::CoreOutOfRange( title_
, args
, target_i
, "The target can not be specified for remote destinations." );
2131 static Lang::Symbol
SIDES_TopLeft( "topleft" );
2132 static Lang::Symbol
SIDES_Page( "page" );
2133 static Lang::Symbol
SIDES_Top( "top" );
2134 static Lang::Symbol
SIDES_Left( "left" );
2135 static Lang::Symbol
SIDES_Rectangle( "rectangle" );
2136 if( sidesVal
!= NullPtr
< SidesModeType
>( ) )
2138 if( *sidesVal
== SIDES_TopLeft
)
2140 sides
= Lang::DocumentDestination::TOPLEFT
;
2142 else if( *sidesVal
== SIDES_Page
)
2144 if( target
!= NullPtr
< TargetType
>( ) )
2146 throw Exceptions::CoreOutOfRange( title_
, args
, sidesMode_i
, "The sides mode cannot be page when a target object is present." );
2148 sides
= Lang::DocumentDestination::PAGE
;
2150 else if( *sidesVal
== SIDES_Top
)
2152 sides
= Lang::DocumentDestination::TOP
;
2154 else if( *sidesVal
== SIDES_Left
)
2156 sides
= Lang::DocumentDestination::LEFT
;
2158 else if( *sidesVal
== SIDES_Rectangle
)
2160 sides
= Lang::DocumentDestination::RECTANGLE
;
2164 std::ostringstream oss
;
2165 oss
<< "Valid sides modes are the symbols { "
2166 << SIDES_TopLeft
.name( ).getPtr( ) << ", "
2167 << SIDES_Page
.name( ).getPtr( ) << ", "
2168 << SIDES_Top
.name( ).getPtr( ) << ", "
2169 << SIDES_Left
.name( ).getPtr( ) << ", "
2170 << SIDES_Rectangle
.name( ).getPtr( )
2172 throw Exceptions::CoreOutOfRange( title_
, args
, sidesMode_i
, strrefdup( oss
) );
2177 typedef const Lang::Boolean FitToType
;
2178 RefCountPtr
< FitToType
> fittobboxVal
= Helpers::down_cast_CoreArgument
< FitToType
>( title_
, args
, argsi
, callLoc
, true );
2179 bool fittobbox
= false;
2180 if( fittobboxVal
!= NullPtr
< FitToType
>( ) )
2182 if( remote
|| sides
== Lang::DocumentDestination::TOPLEFT
|| sides
== Lang::DocumentDestination::RECTANGLE
)
2184 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "The fit-to-bbox flag cannot be specified in this mode." );
2186 fittobbox
= fittobboxVal
->val_
;
2190 typedef const Lang::Float ZoomType
;
2191 RefCountPtr
< ZoomType
> zoomVal
= Helpers::down_cast_CoreArgument
< ZoomType
>( title_
, args
, argsi
, callLoc
, true );
2192 double zoom
= 0; // This will remain zero only if the zoom argument is not specified.
2193 if( zoomVal
!= NullPtr
< ZoomType
>( ) )
2195 if( remote
|| sides
!= Lang::DocumentDestination::TOPLEFT
)
2197 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "The zoom can only be specified when using the top-left sides." );
2199 zoom
= zoomVal
->val_
;
2202 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "The zoom value must be positive." );
2207 typedef const Lang::Boolean DoTransformType
;
2208 bool doTransform
= Helpers::down_cast_CoreArgument
< DoTransformType
>( title_
, args
, argsi
, callLoc
)->val_
;
2210 Kernel::ContRef cont
= evalState
->cont_
;
2213 RefCountPtr
< const Lang::DocumentDestination
>
2214 taggedObj( new Lang::DocumentDestination( remote
, name
, outlineLevel
,
2215 outlineText
, outlineOpen
, outlineBold
, outlineItalic
, outlineColor
) );
2216 cont
->takeValue( RefCountPtr
< const Lang::Value
>
2217 ( new Lang::TaggedValue2D( Kernel::THE_NAVIGATION_SYMBOL
, taggedObj
) ),
2222 RefCountPtr
< const Lang::DocumentDestination
>
2223 taggedObj( new Lang::DocumentDestination( name
, outlineLevel
,
2224 outlineText
, outlineOpen
, outlineBold
, outlineItalic
, outlineColor
,
2225 sides
, target
, fittobbox
, zoom
) );
2228 cont
->takeValue( RefCountPtr
< const Lang::Value
>
2229 ( new Lang::TaggedGeometric2D( Kernel::THE_NAVIGATION_SYMBOL
, taggedObj
) ),
2234 cont
->takeValue( RefCountPtr
< const Lang::Value
>
2235 ( new Lang::TaggedValue2D( Kernel::THE_NAVIGATION_SYMBOL
, taggedObj
) ),
2242 class Core_importFont
: public Lang::CoreFunction
2248 RefCountPtr
< const char > filename_
;
2249 CacheKey( bool outline
, const RefCountPtr
< const char > & filename
)
2250 : outline_( outline
), filename_( filename
)
2254 bool operator < ( const CacheKey
& other
) const
2256 if( ! outline_
&& other
.outline_
)
2260 if( outline_
&& ! other
.outline_
)
2264 return strcmp( filename_
.getPtr( ), other
.filename_
.getPtr( ) ) < 0;
2268 static std::map
< CacheKey
, RefCountPtr
< const Lang::Value
> > cache
;
2270 Core_importFont( const char * title
)
2271 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
2273 formals_
->appendEvaluatedCoreFormal( "family", Kernel::THE_SLOT_VARIABLE
);
2274 formals_
->appendEvaluatedCoreFormal( "style", Kernel::THE_VOID_VARIABLE
);
2275 formals_
->appendEvaluatedCoreFormal( "outline", Kernel::THE_FALSE_VARIABLE
);
2278 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2281 throw Exceptions::BuildRequirement( Interaction::BUILD_REQ_FREETYPE
, title_
, callLoc
);
2283 args
.applyDefaults( );
2286 std::string full_filename
;
2287 #ifndef HAVE_FONTCONFIG
2288 /* Here, it would be possible to allow the user to point out the font file directly instead of using FontConfig,
2289 * but currently there is no such option.
2291 throw Exceptions::BuildRequirement( Interaction::BUILD_REQ_FONTCONFIG
, title_
, callLoc
);
2293 FcPattern
* pat
= FcPatternCreate( );
2294 Helpers::AutoDestroyFcPattern
destroy_pat( pat
);
2296 FcValue fc_fontformat
;
2297 fc_fontformat
.type
= FcTypeString
;
2298 fc_fontformat
.u
.s
= reinterpret_cast< const FcChar8
* >( "TrueType" );
2299 FcPatternAdd( pat
, "fontformat", fc_fontformat
, FcFalse
);
2301 size_t argsi_family
= argsi
;
2302 typedef const Lang::String ArgType
;
2303 RefCountPtr
< ArgType
> family
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, argsi_family
, callLoc
);
2305 fc_family
.type
= FcTypeString
;
2306 fc_family
.u
.s
= reinterpret_cast< const FcChar8
* >( family
->val_
.getPtr( ) );
2307 FcPatternAdd( pat
, "family", fc_family
, FcFalse
);
2310 size_t argsi_style
= argsi
;
2311 RefCountPtr
< ArgType
> style
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, argsi_style
, callLoc
, true );
2313 if( style
!= NullPtr
< ArgType
>( ) )
2315 fc_style
.type
= FcTypeString
;
2316 fc_style
.u
.s
= reinterpret_cast< const FcChar8
* >( style
->val_
.getPtr( ) );
2317 FcPatternAdd( pat
, "style", fc_family
, FcFalse
);
2320 FcFontSet
* sysFonts
= FcConfigGetFonts( NULL
, FcSetSystem
);
2324 FcDefaultSubstitute( pat
);
2325 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. */
2326 FcPattern
* match_res
= FcFontSetMatch( NULL
, & sysFonts
, 1, pat
, & fc_res
);
2327 if( match_res
== 0 )
2329 throw Exceptions::ExternalError( "FontConfig' FcFontSetMatch returned with failure." );
2331 Helpers::AutoDestroyFcPattern
destroy_match_res( match_res
);
2336 // OK, just continue;
2338 case FcResultNoMatch
:
2339 throw Exceptions::OutOfRange( callLoc
, "FontConfig returned no matching font." );
2340 case FcResultOutOfMemory
:
2341 throw Exceptions::ExternalError( "FontConfig got out of memory." );
2342 case FcResultTypeMismatch
:
2344 // std::ostringstream msg;
2345 // msg << "Unexpected FcResult from FcFontSetMatch: " << "FcResultTypeMismatch" << " (ignored)." ;
2346 // WARN_OR_THROW( Exceptions::InternalError( strrefdup( msg ), true ) );
2351 // std::ostringstream msg;
2352 // msg << "Unexpected FcResult from FcFontSetMatch: " << "FcResultNoId" << " (ignored)." ;
2353 // WARN_OR_THROW( Exceptions::InternalError( strrefdup( msg ), true ) );
2358 // std::ostringstream msg;
2359 // msg << "Unexpected FcResult from FcFontSetMatch: " << fc_res << " (ignored)." ;
2360 // WARN_OR_THROW( Exceptions::InternalError( strrefdup( msg ), true ) );
2362 // throw Exceptions::InternalError( "Unexpected FcResult from FcFontSetMatch." );
2365 // FcPatternPrint( match_res );
2367 FcChar8
* fc_tmp_string
;
2368 switch( FcPatternGetString( match_res
, "fontformat", 0, & fc_tmp_string
) )
2371 // OK, just continue;
2373 case FcResultNoMatch
:
2374 throw Exceptions::ExternalError( "FontConfig says that the font does not have a 'fontformat'." );
2375 case FcResultTypeMismatch
:
2376 throw Exceptions::ExternalError( "FontConfig says 'fontformat' has the wrong type." );
2378 throw Exceptions::ExternalError( "FontConfig says 'fontformat' is missing something." );
2379 case FcResultOutOfMemory
:
2380 throw Exceptions::ExternalError( "FontConfig got out of memory." );
2382 if( strcmp( reinterpret_cast< const char * >( fc_tmp_string
), "TrueType" ) != 0 ) // This is OK, since "TrueType" is in the ASCII range.
2384 throw Exceptions::OutOfRange( callLoc
, "Font file format not supported by Shapes, only TrueType is supported at the moment." );
2387 switch( FcPatternGetString( match_res
, "file", 0, & fc_tmp_string
) )
2390 // OK, just continue;
2392 case FcResultNoMatch
:
2393 throw Exceptions::ExternalError( "FontConfig says that the font does not have a 'file' (filename)." );
2394 case FcResultTypeMismatch
:
2395 throw Exceptions::ExternalError( "FontConfig says 'file' has the wrong type." );
2397 throw Exceptions::ExternalError( "FontConfig says 'file' is missing something." );
2398 case FcResultOutOfMemory
:
2399 throw Exceptions::ExternalError( "FontConfig got out of memory." );
2401 full_filename
= reinterpret_cast< const char * >( fc_tmp_string
); /* Let us hope that this string is in the ASCII range! */
2405 size_t argsi_outline
= argsi
;
2406 bool outline
= Helpers::down_cast_CoreArgument
< const Lang::Boolean
>( title_
, args
, argsi_outline
, callLoc
)->val_
;
2407 CacheKey
cacheKey( outline
, strrefdup( full_filename
.c_str( ) ) );
2409 typedef typeof cache MapType
;
2410 MapType::const_iterator i
= cache
.find( cacheKey
);
2411 if( i
!= cache
.end( ) )
2413 Kernel::ContRef cont
= evalState
->cont_
;
2414 cont
->takeValue( i
->second
,
2422 FT_Error error
= FT_New_Face( Kernel::theFreeType
,
2423 full_filename
.c_str( ),
2426 if( error
== FT_Err_Unknown_File_Format
)
2428 throw Exceptions::ExternalError( "Font file format not supported by FreeType." );
2430 else if( error
!= 0 )
2432 std::ostringstream msg
;
2433 msg
<< "FreeType failed to open " << full_filename
<< ", reason: " << Kernel::FreeTypeErrorMessage( error
) ;
2434 throw Exceptions::ExternalError( strrefdup( msg
) );
2437 const char * PostScriptName
= FT_Get_Postscript_Name( face
); /* See comment on the next line! */
2438 std::ostringstream baseFontName
; /* The PostScriptName pointer shall only be used as long as this object is in scope. */
2439 if( PostScriptName
== 0 )
2441 for( const char * src
= full_filename
.c_str( ); *src
!= '\0'; ++src
)
2449 baseFontName
<< *src
;
2452 PostScriptName
= baseFontName
.str( ).c_str( );
2455 if( ! FT_IS_SFNT( face
) )
2457 throw Exceptions::OutOfRange( callLoc
, "Font file format not supported by Shapes, only TrueType is supported at the moment." );
2462 FT_UShort fsType
= FT_Get_FSType_Flags( face
);
2463 if( ( fsType
& ( FT_FSTYPE_INSTALLABLE_EMBEDDING
|
2464 FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING
|
2465 FT_FSTYPE_EDITABLE_EMBEDDING
) )
2468 std::ostringstream msg
;
2469 msg
<< "The font " << PostScriptName
<< " does not permit embedding, and cannot be used with Shapes. Flags: " << std::hex
<< static_cast< int >( fsType
) << "." ;
2470 throw Exceptions::MiscellaneousRequirement( strrefdup( msg
) );
2473 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." ) );
2477 FontMetrics::FreeType2_Metric
* newMetrics
= new FontMetrics::FreeType2_Metric( face
);
2478 RefCountPtr
< const FontMetrics::FontMetric
> metrics
= RefCountPtr
< const FontMetrics::FontMetric
>( newMetrics
);
2480 RefCountPtr
< SimplePDF::PDF_Dictionary
> dic
;
2481 RefCountPtr
< SimplePDF::PDF_Object
> resource
= SimplePDF::indirect( dic
, & Kernel::theIndirectObjectCount
);
2482 (*dic
)[ "Type" ] = SimplePDF::newName( "Font" );
2483 (*dic
)[ "Subtype" ] = SimplePDF::newName( "Type0" );
2485 RefCountPtr
< SimplePDF::PDF_Dictionary
> descendant
;
2486 RefCountPtr
< SimplePDF::PDF_Vector
> descendants
;
2487 descendants
->vec
.push_back( descendant
);
2488 (*dic
)[ "DescendantFonts" ] = descendants
;
2490 RefCountPtr
< SimplePDF::PDF_ToUnicode::CharSet
> usedChars
;
2492 (*descendant
)[ "Type" ] = SimplePDF::newName( "Font" );
2493 (*descendant
)[ "Subtype" ] = SimplePDF::newName( "CIDFontType2" );
2495 RefCountPtr
< SimplePDF::PDF_Name
> fontName
= RefCountPtr
< SimplePDF::PDF_Name
>( new SimplePDF::PDF_Name( PostScriptName
) );
2496 (*dic
)[ "BaseFont" ] = fontName
;
2497 (*descendant
)[ "BaseFont" ] = fontName
;
2498 (*dic
)[ "Encoding" ] = SimplePDF::newName( "Identity-H" );
2499 (*descendant
)[ "BaseFont" ] = fontName
;
2501 RefCountPtr
< SimplePDF::PDF_Dictionary
> CIDSystemInfo
;
2502 (*CIDSystemInfo
)[ "Registry" ] = SimplePDF::newString( "Adobe" );
2503 (*CIDSystemInfo
)[ "Ordering" ] = SimplePDF::newString( "Identity" );
2504 (*CIDSystemInfo
)[ "Supplement" ] = SimplePDF::newString( "0" );
2505 (*descendant
)[ "CIDSystemInfo" ] = CIDSystemInfo
;
2506 (*descendant
)[ "CIDToGIDMap" ] = SimplePDF::newName( "Identity" );
2508 (*descendant
)[ "DW" ] = SimplePDF::newFloat( 0.7 * 1000 ); /* Default width. */
2510 RefCountPtr
< SimplePDF::PDF_Dictionary
> fontDescriptor
;
2511 (*fontDescriptor
)[ "Type" ] = SimplePDF::newName( "FontDescriptor" );
2512 (*fontDescriptor
)[ "FontName" ] = fontName
;
2513 (*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...
2514 (*fontDescriptor
)[ "FontBBox" ] =
2515 RefCountPtr
< SimplePDF::PDF_Vector
>( new SimplePDF::PDF_Vector( newMetrics
->fontBBoxXMin_
* 1000, newMetrics
->fontBBoxYMin_
* 1000,
2516 newMetrics
->fontBBoxXMax_
* 1000, newMetrics
->fontBBoxYMax_
* 1000 ) );
2517 (*fontDescriptor
)[ "ItalicAngle" ] = SimplePDF::newFloat( 0 );
2518 (*fontDescriptor
)[ "Ascent" ] = SimplePDF::newFloat( 1 * 1000 );
2519 (*fontDescriptor
)[ "Descent" ] = SimplePDF::newFloat( -0.5 * 1000 );
2521 RefCountPtr
< SimplePDF::PDF_Stream_out
> fontFile
= RefCountPtr
< SimplePDF::PDF_Stream_out
>( new SimplePDF::PDF_Stream_out( ) );
2522 (*fontFile
)[ "Filter" ] = SimplePDF::newName( "FlateDecode" );
2523 std::ifstream
iFile( full_filename
.c_str( ) );
2524 if( ! iFile
.is_open( ) )
2526 throw Exceptions::FileReadOpenError( callLoc
, strrefdup( full_filename
), 0, 0 );
2529 iFile
.seekg( 0, std::ios::end
);
2530 std::streamoff tmp
= iFile
.tellg( );
2531 std::streamsize size
= tmp
- static_cast< std::streamoff
>( 0 );
2532 (*fontFile
)[ "Length1" ] = SimplePDF::newInt( size
);
2533 char * buf
= new char[ size
];
2534 iFile
.seekg( 0, std::ios::beg
);
2535 iFile
.read( buf
, size
);
2536 fontFile
->data
.write( buf
, size
);
2539 (*fontDescriptor
)[ "FontFile2" ] = SimplePDF::indirect( fontFile
, & Kernel::theIndirectObjectCount
);
2541 (*descendant
)[ "FontDescriptor" ] = fontDescriptor
;
2543 RefCountPtr
< const Lang::Font
> res
= RefCountPtr
< const Lang::Font
>( new Lang::FreeTypeFont( face
,
2544 newMetrics
->fontName_
,
2549 RefCountPtr
< SimplePDF::PDF_ToUnicode
> toUnicode( new SimplePDF::PDF_ToUnicode( usedChars
, res
) );
2550 (*dic
)[ "ToUnicode" ] = SimplePDF::indirect( toUnicode
, & Kernel::theIndirectObjectCount
);
2551 RefCountPtr
< SimplePDF::PDF_Widths
> widths( new SimplePDF::PDF_Widths( usedChars
, res
) );
2552 (*descendant
)[ "W" ] = SimplePDF::indirect( widths
, & Kernel::theIndirectObjectCount
);
2555 typedef typeof cache MapType
;
2556 cache
.insert( MapType::value_type( cacheKey
, res
) );
2558 Kernel::ContRef cont
= evalState
->cont_
;
2559 cont
->takeValue( res
,
2565 std::map
< Core_importFont::CacheKey
, RefCountPtr
< const Lang::Value
> > Core_importFont::cache
;
2567 class Core_Unicode
: public Lang::CoreFunction
2570 Core_Unicode( const char * title
)
2571 : CoreFunction( title
)
2574 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2576 const size_t ARITY
= 1;
2577 CHECK_ARITY( args
, ARITY
, title_
);
2580 typedef const Lang::Integer ArgType
;
2581 ArgType::ValueType arg
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, argsi
, callLoc
)->val_
;
2584 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "Unicode code points cannot be negative." );
2587 Kernel::ContRef cont
= evalState
->cont_
;
2588 cont
->takeValue( Kernel::ValueRef( new Lang::Character( arg
) ),
2593 class Core_AdobeGlyphList
: public Lang::CoreFunction
2596 Core_AdobeGlyphList( const char * title
)
2597 : CoreFunction( title
)
2600 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2602 const size_t ARITY
= 1;
2603 CHECK_ARITY( args
, ARITY
, title_
);
2606 typedef const Lang::Symbol ArgType
;
2607 RefCountPtr
< ArgType
> arg
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, argsi
, callLoc
);
2608 if( arg
->isUnique( ) )
2610 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "Unique symbols do not correspond to any glyphs." );
2612 FontMetrics::GlyphList::UnicodeType res
;
2613 const FontMetrics::GlyphList
& glyphList
= Helpers::requireGlyphList( );
2614 if( ! glyphList
.name_to_UCS4( arg
->name( ).getPtr( ), & res
) )
2616 std::ostringstream msg
;
2617 msg
<< "Unrecognized glyph name: " ;
2619 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, strrefdup( msg
) );
2621 Kernel::ContRef cont
= evalState
->cont_
;
2622 cont
->takeValue( Kernel::ValueRef( new Lang::Character( res
) ),
2631 Lang::Core_range::Core_range( const char * title
)
2632 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
2634 formals_
->appendEvaluatedCoreFormal( "begin", Kernel::THE_VOID_VARIABLE
);
2635 formals_
->appendEvaluatedCoreFormal( "end", Kernel::THE_VOID_VARIABLE
);
2636 formals_
->appendEvaluatedCoreFormal( "step", Kernel::THE_VOID_VARIABLE
);
2637 formals_
->appendEvaluatedCoreFormal( "count", Kernel::THE_VOID_VARIABLE
);
2641 Lang::Core_range::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2643 makeRange( title_
, evalState
, args
, callLoc
);
2647 Lang::Core_range::makeRange( const char * title
, Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
, bool isSpan
, RefCountPtr
< const Lang::Value
> lastPtr
)
2649 const size_t argsi_begin
= 0;
2650 const size_t argsi_end
= 1;
2651 const size_t argsi_step
= 2;
2652 const size_t argsi_count
= 3;
2654 typedef const Lang::Integer CountType
;
2656 args
.applyDefaults( );
2660 typedef const Lang::Integer ArgType
;
2662 RefCountPtr
< ArgType
> beginPtr
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi_begin
), true );
2663 RefCountPtr
< ArgType
> endPtr
= Helpers::down_cast_CoreArgument
< ArgType
>( title
, args
, argsi_end
, callLoc
, true );
2664 if( beginPtr
== NullPtr
< ArgType
>( ) && endPtr
== NullPtr
< ArgType
>( ) )
2666 throw Exceptions::CoreRequirement( "At least one of the arguments <begin> and <end> must be provided.", title
, callLoc
);
2668 RefCountPtr
< ArgType
> stepPtr
= Helpers::down_cast_CoreArgument
< ArgType
>( title
, args
, argsi_step
, callLoc
, true );
2669 RefCountPtr
< CountType
> countPtr
= Helpers::down_cast_CoreArgument
< CountType
>( title
, args
, argsi_count
, callLoc
, true );
2671 if( beginPtr
!= NullPtr
< ArgType
>( ) && endPtr
!= NullPtr
< ArgType
>( ) &&
2672 stepPtr
!= NullPtr
< ArgType
>( ) && countPtr
!= NullPtr
< CountType
>( ) )
2674 throw Exceptions::CoreRequirement( "At least one of the arguments must be omitted.", title
, callLoc
);
2677 ArgType::ValueType begin
= 0;
2678 ArgType::ValueType step
= 1;
2679 ArgType::ValueType last
= isSpan
? lastPtr
.down_cast
< ArgType
>( )->val_
: 0;
2682 if( stepPtr
!= NullPtr
< ArgType
>( ) )
2684 step
= stepPtr
->val_
;
2686 if( countPtr
!= NullPtr
< CountType
>( ) )
2688 if( countPtr
->val_
< 0 )
2690 throw Exceptions::CoreOutOfRange( title
, args
, argsi_count
, "The <count> must not be negative." );
2692 count
= countPtr
->val_
;
2695 if( beginPtr
== NullPtr
< ArgType
>( ) )
2697 if( countPtr
== NullPtr
< CountType
>( ) )
2701 if( endPtr
->val_
< 0 )
2703 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a span of integers and <begin> is omitted while <end> is negative.", title
, callLoc
);
2705 count
= 1 + endPtr
->val_
/ step
;
2709 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of integers and <begin> is omitted.", title
, callLoc
);
2712 begin
= endPtr
->val_
- ( count
- 1 ) * step
;
2714 else if( endPtr
== NullPtr
< ArgType
>( ) )
2716 begin
= beginPtr
->val_
;
2717 if( countPtr
== NullPtr
< CountType
>( ) )
2723 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of integers and <end> is omitted while <begin> exceeds %last.", title
, callLoc
);
2725 count
= ( last
- begin
) / step
+ 1;
2729 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of integers and <end> is omitted.", title
, callLoc
);
2735 if( countPtr
!= NullPtr
< CountType
>( ) )
2737 throw Exceptions::CoreRequirement( "It is an error to provide the <count> argument when constructing a range of integers from <begin> to <end>.", title
, args
.getLoc( argsi_count
) );
2740 begin
= beginPtr
->val_
;
2741 if( ( endPtr
->val_
>= begin
&& step
<= 0 )
2743 ( endPtr
->val_
<= begin
&& step
>= 0 ) )
2745 throw Exceptions::CoreOutOfRange( title
, args
, argsi_step
, "When <count> is omitted, the sign of <step> must agree with the order of <begin> and <end>." );
2747 count
= 1 + ( endPtr
->val_
- begin
) / step
;
2750 Kernel::ContRef cont
= evalState
->cont_
;
2753 cont
->takeValue( Lang::THE_CONS_NULL
,
2758 cont
->takeValue( RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListRange
< ArgType
>( begin
, step
, count
) ),
2763 catch( const NonLocalExit::NotThisType
& ball
)
2765 // Never mind, see below
2770 typedef const Lang::Float ArgType
;
2772 RefCountPtr
< ArgType
> beginPtr
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi_begin
), true );
2773 RefCountPtr
< ArgType
> endPtr
= Helpers::down_cast_CoreArgument
< ArgType
>( title
, args
, argsi_end
, callLoc
, true );
2774 if( beginPtr
== NullPtr
< ArgType
>( ) && endPtr
== NullPtr
< ArgType
>( ) )
2776 throw Exceptions::CoreRequirement( "At least one of the arguments <begin> and <end> must be provided.", title
, callLoc
);
2778 RefCountPtr
< ArgType
> stepPtr
= Helpers::down_cast_CoreArgument
< ArgType
>( title
, args
, argsi_step
, callLoc
, true );
2779 RefCountPtr
< CountType
> countPtr
= Helpers::down_cast_CoreArgument
< CountType
>( title
, args
, argsi_count
, callLoc
, true );
2781 if( beginPtr
!= NullPtr
< ArgType
>( ) && endPtr
!= NullPtr
< ArgType
>( ) &&
2782 stepPtr
!= NullPtr
< ArgType
>( ) && countPtr
!= NullPtr
< CountType
>( ) )
2784 throw Exceptions::CoreRequirement( "At least one of the arguments must be omitted.", title
, callLoc
);
2787 ArgType::ValueType begin
= 0;
2788 ArgType::ValueType step
= 1;
2789 ArgType::ValueType last
= isSpan
? lastPtr
.down_cast
< ArgType
>( )->val_
: 0;
2792 if( stepPtr
!= NullPtr
< ArgType
>( ) )
2794 step
= stepPtr
->val_
;
2796 if( countPtr
!= NullPtr
< CountType
>( ) )
2798 if( countPtr
->val_
< 0 )
2800 throw Exceptions::CoreOutOfRange( title
, args
, argsi_count
, "The <count> must not be negative." );
2802 count
= countPtr
->val_
;
2805 if( beginPtr
== NullPtr
< ArgType
>( ) )
2807 if( countPtr
== NullPtr
< CountType
>( ) )
2811 if( endPtr
->val_
< 0 )
2813 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a span of floats and <begin> is omitted while <end> is negative.", title
, callLoc
);
2815 count
= 1 + static_cast< size_t >( endPtr
->val_
/ step
);
2819 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of floats and <begin> is omitted.", title
, callLoc
);
2822 begin
= endPtr
->val_
- ( count
- 1 ) * step
;
2824 else if( endPtr
== NullPtr
< ArgType
>( ) )
2826 begin
= beginPtr
->val_
;
2827 if( countPtr
== NullPtr
< CountType
>( ) )
2833 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of floats and <end> is omitted while <begin> exceeds %last.", title
, callLoc
);
2835 count
= 1 + static_cast< size_t >( ( last
- begin
) / step
);
2839 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of floats and <end> is omitted.", title
, callLoc
);
2845 begin
= beginPtr
->val_
;
2846 // When we reach here, we know that at most one of <step> and <count> is provided.
2847 if( countPtr
!= NullPtr
< CountType
>( ) )
2851 throw Exceptions::CoreOutOfRange( title
, args
, argsi_count
, "When <step> is omitted, the <count> be at least 2." );
2853 step
= ( endPtr
->val_
- begin
) / ( count
- 1 );
2857 /* If <step> is not provided, it defaults to 1, see above. */
2860 throw Exceptions::CoreOutOfRange( title
, args
, argsi_step
, "When <count> is omitted, <step> must not be zero." );
2862 ArgType::ValueType tmpCount
= 1 + ( endPtr
->val_
- begin
) / step
;
2869 if( tmpCount
> std::numeric_limits
< size_t >::max( ) )
2871 throw Exceptions::CoreOutOfRange( title
, args
, argsi_step
, "When <count> is omitted, too small <step> values cause overflow in the number of elements." );
2873 count
= static_cast< size_t >( tmpCount
);
2878 Kernel::ContRef cont
= evalState
->cont_
;
2881 cont
->takeValue( Lang::THE_CONS_NULL
,
2886 cont
->takeValue( RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListRange
< ArgType
>( begin
, step
, count
) ),
2891 catch( const NonLocalExit::NotThisType
& ball
)
2893 // Never mind, see below
2898 typedef const Lang::Length ArgType
;
2900 RefCountPtr
< ArgType
> beginPtr
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi_begin
), true );
2901 RefCountPtr
< ArgType
> endPtr
= Helpers::down_cast_CoreArgument
< ArgType
>( title
, args
, argsi_end
, callLoc
, true );
2902 if( beginPtr
== NullPtr
< ArgType
>( ) && endPtr
== NullPtr
< ArgType
>( ) )
2904 throw Exceptions::CoreRequirement( "At least one of the arguments <begin> and <end> must be provided.", title
, callLoc
);
2906 RefCountPtr
< ArgType
> stepPtr
= Helpers::down_cast_CoreArgument
< ArgType
>( title
, args
, argsi_step
, callLoc
, true );
2907 RefCountPtr
< CountType
> countPtr
= Helpers::down_cast_CoreArgument
< CountType
>( title
, args
, argsi_count
, callLoc
, true );
2909 if( beginPtr
!= NullPtr
< ArgType
>( ) && endPtr
!= NullPtr
< ArgType
>( ) &&
2910 stepPtr
!= NullPtr
< ArgType
>( ) && countPtr
!= NullPtr
< CountType
>( ) )
2912 throw Exceptions::CoreRequirement( "At least one of the arguments must be omitted.", title
, callLoc
);
2915 ArgType::ValueType begin
= ArgType::ValueType( 0 );
2916 ArgType::ValueType step
= ArgType::ValueType( 1 ); /* This is a "default" value that one is not allowed to use! */
2917 ArgType::ValueType last
= isSpan
? lastPtr
.down_cast
< ArgType
>( )->get( ) : Concrete::ZERO_LENGTH
;
2920 if( stepPtr
!= NullPtr
< ArgType
>( ) )
2922 step
= stepPtr
->get( );
2924 if( countPtr
!= NullPtr
< CountType
>( ) )
2926 if( countPtr
->val_
< 0 )
2928 throw Exceptions::CoreOutOfRange( title
, args
, argsi_count
, "The <count> must not be negative." );
2930 count
= countPtr
->val_
;
2933 if( beginPtr
== NullPtr
< ArgType
>( ) )
2935 if( stepPtr
== NullPtr
< ArgType
>( ) )
2937 throw Exceptions::CoreRequirement( "The <step> must be provided when constructing a range of lengths when <begin> is omitted.", title
, callLoc
);
2939 if( countPtr
== NullPtr
< CountType
>( ) )
2943 if( endPtr
->get( ) < Concrete::ZERO_LENGTH
)
2945 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a span of lengths and <begin> is omitted while <end> is negative.", title
, callLoc
);
2947 count
= 1 + static_cast< size_t >( endPtr
->get( ) / step
);
2951 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of lengths and <begin> is omitted.", title
, callLoc
);
2954 begin
= endPtr
->get( ) - ( count
- 1 ) * step
;
2956 else if( endPtr
== NullPtr
< ArgType
>( ) )
2958 begin
= beginPtr
->get( );
2959 if( stepPtr
== NullPtr
< ArgType
>( ) )
2961 throw Exceptions::CoreRequirement( "The <step> must be provided when constructing a range of lengths when <end> is omitted.", title
, callLoc
);
2963 if( countPtr
== NullPtr
< CountType
>( ) )
2969 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of lengths and <end> is omitted while <begin> exceeds %last.", title
, callLoc
);
2971 count
= static_cast< size_t >( ( last
- begin
) / step
) + 1;
2975 throw Exceptions::CoreRequirement( "The <count> must be provided when constructing a range of lengths and <end> is omitted.", title
, callLoc
);
2981 begin
= beginPtr
->get( );
2982 if( stepPtr
== NullPtr
< ArgType
>( ) && countPtr
== NullPtr
< CountType
>( ) )
2984 throw Exceptions::CoreRequirement( "Either of the <step> and <count> arguments must be provided when constructing a range of lengths from <begin> to <end>.", title
, callLoc
);
2986 // When we reach here, we know that exactly one of <step> and <count> is provided.
2987 if( stepPtr
!= NullPtr
< ArgType
>( ) )
2991 throw Exceptions::CoreOutOfRange( title
, args
, argsi_step
, "When <count> is omitted, <step> must not be zero." );
2993 double tmpCount
= 1 + ( endPtr
->get( ) - begin
) / step
;
3000 if( tmpCount
> std::numeric_limits
< size_t >::max( ) )
3002 throw Exceptions::CoreOutOfRange( title
, args
, argsi_step
, "When <count> is omitted, too small <step> values cause overflow in the number of elements." );
3004 count
= static_cast< size_t >( tmpCount
);
3011 throw Exceptions::CoreOutOfRange( title
, args
, argsi_count
, "When <step> is omitted, the <count> be at least 2." );
3013 step
= ( endPtr
->get( ) - begin
) / ( count
- 1 );
3017 Kernel::ContRef cont
= evalState
->cont_
;
3020 cont
->takeValue( Lang::THE_CONS_NULL
,
3025 cont
->takeValue( RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListRange
< ArgType
>( begin
, step
, count
) ),
3030 catch( const NonLocalExit::NotThisType
& ball
)
3032 // Never mind, see below
3035 throw Exceptions::CoreTypeMismatch( callLoc
, title
, args
, 0, Helpers::typeSetString( Lang::Integer::staticTypeName( ), Lang::Float::staticTypeName( ), Lang::Length::staticTypeName( ) ) );
3040 * To avoid problems with initialization order (Kernel::THE_VOID_VARIABLE has to be initialized first), we first
3041 * initialize with an ugly null value, and then set the correct value when the real function is registered below.
3043 RefCountPtr
< const Lang::CoreFunction
> Lang::THE_FUNCTION_RANGE
= RefCountPtr
< const Lang::CoreFunction
>( NullPtr
< const Lang::CoreFunction
>( ) );
3046 Kernel::registerCore_construct( Kernel::Environment
* env
)
3048 Lang::THE_FUNCTION_RANGE
= RefCountPtr
< const Lang::CoreFunction
>( new Lang::Core_range( "range" ) );
3050 env
->initDefineCoreFunction( new Lang::Core_cons( "cons" ) );
3051 env
->initDefineCoreFunction( new Lang::Core_list( "list" ) );
3052 env
->initDefineCoreFunction( new Lang::Core_unlist( "unlist" ) );
3053 env
->initDefineCoreFunction( new Lang::Core_isnull( "null?" ) );
3054 env
->initDefineCoreFunction( Lang::THE_FUNCTION_RANGE
);
3055 env
->initDefineCoreFunction( new Lang::Core_span( "span" ) );
3056 env
->initDefineCoreFunction( new Lang::Core_affinetransform( "affinetransform" ) );
3057 env
->initDefineCoreFunction( new Lang::Core_shift( "shift" ) );
3058 env
->initDefineCoreFunction( new Lang::Core_rotate( "rotate" ) );
3059 env
->initDefineCoreFunction( new Lang::Core_rotate3d( "rotate3D" ) );
3060 env
->initDefineCoreFunction( new Lang::Core_scale( "scale" ) );
3061 env
->initDefineCoreFunction( new Lang::Core_scale3d( "scale3D" ) );
3062 env
->initDefineCoreFunction( new Lang::Core_affinetransform3D( "affinetransform3D" ) );
3063 env
->initDefineCoreFunction( new Lang::Core_inverse( "inverse" ) );
3065 env
->initDefineCoreFunction( new Lang::Core_formxo( "formxo" ) );
3066 env
->initDefineCoreFunction( new Lang::Core_importRasterImage( "import_raster" ) );
3067 env
->initDefineCoreFunction( new Lang::Core_transparencygroup( "tgroup" ) );
3069 env
->initDefineCoreFunction( new Lang::Core_tag( "tag" ) );
3070 env
->initDefineCoreFunction( new Lang::Core_find( "find" ) );
3071 env
->initDefineCoreFunction( new Lang::Core_findall( "findall" ) );
3073 env
->initDefineCoreFunction( new Lang::Core_ambient_light( "ambient_light" ) );
3074 env
->initDefineCoreFunction( new Lang::Core_specular_light( "specular_light" ) );
3075 env
->initDefineCoreFunction( new Lang::Core_distant_light( "distant_light" ) );
3076 env
->initDefineCoreFunction( new Lang::Core_phong( "phong" ) );
3078 env
->initDefineCoreFunction( new Lang::Core_vector( "vector" ) );
3079 env
->initDefineCoreFunction( new Lang::Core_importPDFpages( "import" ) );
3081 env
->initDefineCoreFunction( new Lang::Core_svg_path( "svg_path" ) );
3083 env
->initDefineCoreFunction( new Lang::Core_sprintf( "sprintf" ) );
3084 env
->initDefineCoreFunction( new Lang::Core_strftime( "strftime" ) );
3086 env
->initDefineCoreFunction( new Lang::Core_newrandom( "newRandom" ) );
3087 env
->initDefineCoreFunction( new Lang::Core_devrandom( "devRandom" ) );
3089 env
->initDefineCoreFunction( new Lang::Core_destination( "destination" ) );
3091 env
->initDefineCoreFunction( new Lang::Core_textrenderingmode( "textmode" ) );
3092 env
->initDefineCoreFunction( new Lang::Core_manualkern( "kerning" ) );
3093 env
->initDefineCoreFunction( new Lang::Core_automatickern( "kern" ) );
3095 env
->initDefineCoreFunction( new Lang::Core_importFont( "font" ) );
3097 env
->initDefineCoreFunction( new Lang::Core_Unicode( "Unicode" ) );
3098 env
->initDefineCoreFunction( new Lang::Core_AdobeGlyphList( "AdobeGlyphList" ) );