1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008 Henrik Tidefelt
19 #include "Shapes_Helpers_decls.h"
21 #include "shapescore.h"
22 #include "annotations.h"
24 #include "shapesexceptions.h"
26 #include "simplepdfi.h"
27 #include "simplepdfo.h"
29 #include "continuations.h"
30 #include "pagecontentstates.h"
35 using namespace Shapes
;
42 takeHighlightArgument( const char * coreTitle
, Kernel::Arguments
& args
, size_t i
, const Ast::SourceLocation
& callLoc
)
44 typedef const Lang::Symbol T
;
45 RefCountPtr
< const Lang::Value
> untyped
= args
.getValue( i
);
46 RefCountPtr
< T
> val
= untyped
.down_cast
< T
>( );
48 char highlight
= 'I'; // This is the default.
49 if( val
== NullPtr
< T
>( ) )
51 if( dynamic_cast< const Lang::Void
* >( untyped
.getPtr( ) ) == 0 )
53 throw Exceptions::CoreTypeMismatch( callLoc
, coreTitle
, args
.getLoc( i
), untyped
->getTypeName( ), T::staticTypeName( ) );
58 static Lang::Symbol
HIGHLIGHT_None( "none" );
59 static Lang::Symbol
HIGHLIGHT_Invert( "invert" );
60 static Lang::Symbol
HIGHLIGHT_Outline( "outline" );
61 static Lang::Symbol
HIGHLIGHT_Push( "push" );
62 if( *val
== HIGHLIGHT_None
)
66 else if( *val
== HIGHLIGHT_Invert
)
70 else if( *val
== HIGHLIGHT_Outline
)
74 else if( *val
== HIGHLIGHT_Push
)
80 std::ostringstream oss
;
81 oss
<< "Valid highlight styles are the symbols { "
82 << HIGHLIGHT_None
.name( ).getPtr( ) << ", "
83 << HIGHLIGHT_Invert
.name( ).getPtr( ) << ", "
84 << HIGHLIGHT_Outline
.name( ).getPtr( ) << ", "
85 << HIGHLIGHT_Push
.name( ).getPtr( )
87 throw Exceptions::CoreOutOfRange( coreTitle
, args
, i
, strrefdup( oss
) );
100 class Core_annotationsite
: public Lang::CoreFunction
103 Core_annotationsite( const char * title
)
104 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
106 /* General arguments. Only <target> is required.
108 formals_
->appendEvaluatedCoreFormal( "target", Kernel::THE_SLOT_VARIABLE
);
109 formals_
->appendEvaluatedCoreFormal( "text", Kernel::THE_VOID_VARIABLE
);
110 formals_
->appendEvaluatedCoreFormal( "color", Helpers::newValHandle( new Lang::RGB( Concrete::RGB( 0, 0, 0 ) ) ) );
111 formals_
->appendEvaluatedCoreFormal( "name", Kernel::THE_VOID_VARIABLE
);
113 /* The following define the border.
115 formals_
->appendEvaluatedCoreFormal( "style", Kernel::THE_VOID_VARIABLE
);
116 formals_
->appendEvaluatedCoreFormal( "width", Helpers::newValHandle( new Lang::Length( Concrete::Length( 1 ) ) ) );
117 formals_
->appendEvaluatedCoreFormal( "dash", Kernel::THE_VOID_VARIABLE
);
118 formals_
->appendEvaluatedCoreFormal( "cloudy", Kernel::THE_VOID_VARIABLE
);
120 /* The following are appearances.
122 formals_
->appendEvaluatedCoreFormal( "normal", Kernel::THE_VOID_VARIABLE
);
123 formals_
->appendEvaluatedCoreFormal( "rollover", Kernel::THE_VOID_VARIABLE
);
124 formals_
->appendEvaluatedCoreFormal( "down", Kernel::THE_VOID_VARIABLE
);
126 /* The following boolean arguments correspond to flags.
128 formals_
->appendEvaluatedCoreFormal( "invisible", Kernel::THE_FALSE_VARIABLE
);
129 formals_
->appendEvaluatedCoreFormal( "hidden", Kernel::THE_FALSE_VARIABLE
);
130 formals_
->appendEvaluatedCoreFormal( "print", Kernel::THE_FALSE_VARIABLE
);
131 formals_
->appendEvaluatedCoreFormal( "zoom", Kernel::THE_TRUE_VARIABLE
);
132 formals_
->appendEvaluatedCoreFormal( "rotate", Kernel::THE_TRUE_VARIABLE
);
133 formals_
->appendEvaluatedCoreFormal( "view", Kernel::THE_TRUE_VARIABLE
);
134 formals_
->appendEvaluatedCoreFormal( "writable", Kernel::THE_TRUE_VARIABLE
);
135 formals_
->appendEvaluatedCoreFormal( "locked", Kernel::THE_FALSE_VARIABLE
);
136 formals_
->appendEvaluatedCoreFormal( "toggle", Kernel::THE_FALSE_VARIABLE
);
139 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
141 args
.applyDefaults( );
144 typedef const Lang::Drawable2D TargetType
;
145 RefCountPtr
< TargetType
> target
= Helpers::down_cast_CoreArgument
< TargetType
>( title_
, args
, argsi
, callLoc
);
148 typedef const Lang::String ContentTextType
;
149 RefCountPtr
< ContentTextType
> contentTextVal
= Helpers::down_cast_CoreArgument
< ContentTextType
>( title_
, args
, argsi
, callLoc
, true );
150 RefCountPtr
< const char > contentText
= RefCountPtr
< const char >( NullPtr
< const char >( ) );
151 if( contentTextVal
!= NullPtr
< ContentTextType
>( ) )
153 contentText
= contentTextVal
->val_
;
157 typedef const Lang::RGB ColorType
;
158 Concrete::RGB color
= Helpers::down_cast_CoreArgument
< ColorType
>( title_
, args
, argsi
, callLoc
)->components( );
161 typedef const Lang::String IdentifierType
;
162 RefCountPtr
< IdentifierType
> identifierVal
= Helpers::down_cast_CoreArgument
< IdentifierType
>( title_
, args
, argsi
, callLoc
, true );
163 RefCountPtr
< const char > identifier
= RefCountPtr
< const char >( NullPtr
< const char >( ) );
164 if( identifierVal
!= NullPtr
< IdentifierType
>( ) )
166 identifier
= identifierVal
->val_
;
170 typedef const Lang::Symbol StyleType
;
171 RefCountPtr
< StyleType
> styleVal
= Helpers::down_cast_CoreArgument
< StyleType
>( title_
, args
, argsi
, callLoc
, true );
172 char borderStyle
= 'S';
173 static Lang::Symbol
STYLE_Solid( "solid" );
174 static Lang::Symbol
STYLE_Dashed( "dashed" );
175 static Lang::Symbol
STYLE_Beveled( "beveled" );
176 static Lang::Symbol
STYLE_Inset( "inset" );
177 static Lang::Symbol
STYLE_Underline( "underline" );
178 if( styleVal
!= NullPtr
< StyleType
>( ) )
180 if( *styleVal
== STYLE_Solid
)
184 else if( *styleVal
== STYLE_Dashed
)
188 else if( *styleVal
== STYLE_Beveled
)
192 else if( *styleVal
== STYLE_Inset
)
196 else if( *styleVal
== STYLE_Underline
)
202 std::ostringstream oss
;
203 oss
<< "Valid border styles are the symbols { "
204 << STYLE_Solid
.name( ).getPtr( ) << ", "
205 << STYLE_Dashed
.name( ).getPtr( ) << ", "
206 << STYLE_Beveled
.name( ).getPtr( ) << ", "
207 << STYLE_Inset
.name( ).getPtr( ) << ", "
208 << STYLE_Underline
.name( ).getPtr( )
210 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, strrefdup( oss
) );
215 typedef const Lang::Length WidthType
;
216 Concrete::Length width
= Helpers::down_cast_CoreArgument
< WidthType
>( title_
, args
, argsi
, callLoc
)->get( );
217 if( width
< Concrete::ZERO_LENGTH
)
219 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "The width must be non-negative." );
223 typedef const Lang::Dash DashType
;
224 RefCountPtr
< DashType
> dash
= Helpers::down_cast_CoreArgument
< DashType
>( title_
, args
, argsi
, callLoc
, true );
227 typedef const Lang::Float CloudyType
;
228 RefCountPtr
< CloudyType
> cloudyVal
= Helpers::down_cast_CoreArgument
< CloudyType
>( title_
, args
, argsi
, callLoc
, true );
230 if( cloudyVal
!= NullPtr
< CloudyType
>( ) )
232 cloudy
= cloudyVal
->val_
;
233 if( cloudy
< 0 || cloudy
> 2 )
235 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "The cloudyness parameter is recommended to lie in the range [ 0, 2 ]." );
239 typedef const Lang::XObject AppearanceType
;
241 RefCountPtr
< AppearanceType
> appearanceNormal
= Helpers::down_cast_CoreArgument
< AppearanceType
>( title_
, args
, argsi
, callLoc
, true );
243 RefCountPtr
< AppearanceType
> appearanceRollover
= Helpers::down_cast_CoreArgument
< AppearanceType
>( title_
, args
, argsi
, callLoc
, true );
245 RefCountPtr
< AppearanceType
> appearanceDown
= Helpers::down_cast_CoreArgument
< AppearanceType
>( title_
, args
, argsi
, callLoc
, true );
247 typedef const Lang::Boolean FlagType
;
250 if( Helpers::down_cast_CoreArgument
< FlagType
>( title_
, args
, argsi
, callLoc
)->val_
)
252 flags
= flags
| Lang::AnnotationSite::INVISIBLE
;
255 if( Helpers::down_cast_CoreArgument
< FlagType
>( title_
, args
, argsi
, callLoc
)->val_
)
257 flags
= flags
| Lang::AnnotationSite::HIDDEN
;
260 if( Helpers::down_cast_CoreArgument
< FlagType
>( title_
, args
, argsi
, callLoc
)->val_
)
262 flags
= flags
| Lang::AnnotationSite::PRINT
;
265 if( ! Helpers::down_cast_CoreArgument
< FlagType
>( title_
, args
, argsi
, callLoc
)->val_
)
267 flags
= flags
| Lang::AnnotationSite::NO_ZOOM
;
270 if( ! Helpers::down_cast_CoreArgument
< FlagType
>( title_
, args
, argsi
, callLoc
)->val_
)
272 flags
= flags
| Lang::AnnotationSite::NO_ROTATE
;
275 if( ! Helpers::down_cast_CoreArgument
< FlagType
>( title_
, args
, argsi
, callLoc
)->val_
)
277 flags
= flags
| Lang::AnnotationSite::NO_VIEW
;
280 if( ! Helpers::down_cast_CoreArgument
< FlagType
>( title_
, args
, argsi
, callLoc
)->val_
)
282 flags
= flags
| Lang::AnnotationSite::READ_ONLY
;
285 if( Helpers::down_cast_CoreArgument
< FlagType
>( title_
, args
, argsi
, callLoc
)->val_
)
287 flags
= flags
| Lang::AnnotationSite::LOCKED
;
290 if( Helpers::down_cast_CoreArgument
< FlagType
>( title_
, args
, argsi
, callLoc
)->val_
)
292 flags
= flags
| Lang::AnnotationSite::TOGGLE_NO_VIEW
;
295 Kernel::ContRef cont
= evalState
->cont_
;
296 cont
->takeValue( RefCountPtr
< const Lang::Value
>
297 ( new Lang::AnnotationSite( target
, contentText
, identifier
, flags
,
298 borderStyle
, width
, dash
, cloudy
, color
,
299 appearanceNormal
, appearanceRollover
, appearanceDown
) ),
304 class Core_annotation_text
: public Lang::CoreFunction
307 Core_annotation_text( const char * title
)
308 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
310 /* General arguments. Only <target> is required.
312 formals_
->appendEvaluatedCoreFormal( "site", Kernel::THE_SLOT_VARIABLE
);
313 formals_
->appendEvaluatedCoreFormal( "title", Kernel::THE_VOID_VARIABLE
);
314 formals_
->appendEvaluatedCoreFormal( "open", Kernel::THE_FALSE_VARIABLE
);
315 formals_
->appendEvaluatedCoreFormal( "verifyiconname", Kernel::THE_TRUE_VARIABLE
);
316 formals_
->appendEvaluatedCoreFormal( "icon", Kernel::THE_VOID_VARIABLE
);
319 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
321 args
.applyDefaults( );
324 typedef const Lang::AnnotationSite SiteType
;
325 RefCountPtr
< SiteType
> site
= Helpers::down_cast_CoreArgument
< SiteType
>( title_
, args
, argsi
, callLoc
);
328 typedef const Lang::String TitleType
;
329 RefCountPtr
< TitleType
> titleVal
= Helpers::down_cast_CoreArgument
< TitleType
>( title_
, args
, argsi
, callLoc
, true );
330 RefCountPtr
< const char > title
= RefCountPtr
< const char >( NullPtr
< const char >( ) );
331 if( titleVal
!= NullPtr
< TitleType
>( ) )
333 title
= titleVal
->val_
;
337 typedef const Lang::Boolean InitiallyOpenType
;
338 bool open
= Helpers::down_cast_CoreArgument
< InitiallyOpenType
>( title_
, args
, argsi
, callLoc
)->val_
;
341 typedef const Lang::Boolean VerifyType
;
342 bool verifyIconName
= Helpers::down_cast_CoreArgument
< VerifyType
>( title_
, args
, argsi
, callLoc
)->val_
;
345 typedef const Lang::String IconType
;
346 RefCountPtr
< IconType
> iconVal
= Helpers::down_cast_CoreArgument
< IconType
>( title_
, args
, argsi
, callLoc
, true );
347 RefCountPtr
< const char > icon
= RefCountPtr
< const char >( NullPtr
< const char >( ) );
348 if( iconVal
!= NullPtr
< IconType
>( ) )
350 icon
= iconVal
->val_
;
353 const char * ptr
= icon
.getPtr( );
354 if( strcmp( ptr
, "Comment" ) == 0 )
358 else if( strcmp( ptr
, "Help" ) == 0 )
362 else if( strcmp( ptr
, "Note" ) == 0 )
366 else if( strcmp( ptr
, "Key" ) == 0 )
370 else if( strcmp( ptr
, "Insert" ) == 0 )
374 else if( strcmp( ptr
, "Paragraph" ) == 0 )
378 else if( strcmp( ptr
, "NewParagraph" ) == 0 )
384 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "The icon name is not one of the standard ones. Consider passing false for the <verifyiconname> argument." );
389 Kernel::ContRef cont
= evalState
->cont_
;
390 RefCountPtr
< const Lang::AnnotationBase
>
391 taggedObj( new Lang::TextAnnotation( site
, title
, open
, icon
) );
392 cont
->takeValue( RefCountPtr
< const Lang::Value
>
393 ( new Lang::TaggedValue2D( Kernel::THE_ANNOTATION_SYMBOL
, taggedObj
) ),
398 class Core_annotation_launch
: public Lang::CoreFunction
401 Core_annotation_launch( const char * title
)
402 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
404 /* General arguments. Only <target> is required.
406 formals_
->appendEvaluatedCoreFormal( "site", Kernel::THE_SLOT_VARIABLE
);
407 formals_
->appendEvaluatedCoreFormal( "file", Kernel::THE_SLOT_VARIABLE
);
408 formals_
->appendEvaluatedCoreFormal( "highlight", Kernel::THE_VOID_VARIABLE
);
409 formals_
->appendEvaluatedCoreFormal( "uri", Kernel::THE_VOID_VARIABLE
);
412 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
414 args
.applyDefaults( );
417 typedef const Lang::AnnotationSite SiteType
;
418 RefCountPtr
< SiteType
> site
= Helpers::down_cast_CoreArgument
< SiteType
>( title_
, args
, argsi
, callLoc
);
421 typedef const Lang::String FilenameType
;
422 RefCountPtr
< const char > filename
= Helpers::down_cast_CoreArgument
< FilenameType
>( title_
, args
, argsi
, callLoc
)->val_
;
425 char highlight
= Helpers::takeHighlightArgument( title_
, args
, argsi
, callLoc
);
428 typedef const Lang::Boolean IsURIType
;
429 RefCountPtr
< IsURIType
> isURIVal
= Helpers::down_cast_CoreArgument
< IsURIType
>( title_
, args
, argsi
, callLoc
, true );
430 Lang::LinkAnnotation::Kind kind
= Lang::LinkAnnotation::LAUNCH_FILE
;
431 if( isURIVal
!= NullPtr
< IsURIType
>( ) )
435 kind
= Lang::LinkAnnotation::LAUNCH_URI
;
439 kind
= Lang::LinkAnnotation::LAUNCH_FILE
; // Just in case the default above is changed in the future.
444 const char * str
= filename
.getPtr( );
445 const char alt1
[] = "http://";
446 const char alt2
[] = "https://";
447 const char alt3
[] = "ftp://";
448 const char alt4
[] = "mailto://";
449 if( strncmp( str
, alt1
, strlen( alt1
) ) == 0
450 || strncmp( str
, alt2
, strlen( alt2
) ) == 0
451 || strncmp( str
, alt3
, strlen( alt3
) ) == 0
452 || strncmp( str
, alt4
, strlen( alt4
) ) == 0
455 kind
= Lang::LinkAnnotation::LAUNCH_URI
;
459 kind
= Lang::LinkAnnotation::LAUNCH_FILE
; // Just in case the default above is changed in the future.
463 Kernel::ContRef cont
= evalState
->cont_
;
464 RefCountPtr
< const Lang::AnnotationBase
>
465 taggedObj( new Lang::LinkAnnotation( site
, callLoc
, highlight
, filename
, kind
) );
466 cont
->takeValue( RefCountPtr
< const Lang::Value
>
467 ( new Lang::TaggedValue2D( Kernel::THE_ANNOTATION_SYMBOL
, taggedObj
) ),
472 class Core_annotation_link
: public Lang::CoreFunction
475 Core_annotation_link( const char * title
)
476 : CoreFunction( title
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) )
478 /* General arguments. Only <target> is required.
480 formals_
->appendEvaluatedCoreFormal( "site", Kernel::THE_SLOT_VARIABLE
);
481 formals_
->appendEvaluatedCoreFormal( "name", Kernel::THE_SLOT_VARIABLE
);
482 formals_
->appendEvaluatedCoreFormal( "highlight", Kernel::THE_VOID_VARIABLE
);
485 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
487 args
.applyDefaults( );
490 typedef const Lang::AnnotationSite SiteType
;
491 RefCountPtr
< SiteType
> site
= Helpers::down_cast_CoreArgument
< SiteType
>( title_
, args
, argsi
, callLoc
);
494 typedef const Lang::String IdentifierType
;
495 RefCountPtr
< const char > identifier
= Helpers::down_cast_CoreArgument
< IdentifierType
>( title_
, args
, argsi
, callLoc
)->val_
;
498 char highlight
= Helpers::takeHighlightArgument( title_
, args
, argsi
, callLoc
);
500 Kernel::ContRef cont
= evalState
->cont_
;
501 RefCountPtr
< const Lang::AnnotationBase
>
502 taggedObj( new Lang::LinkAnnotation( site
, callLoc
, highlight
, identifier
, Lang::LinkAnnotation::DOC_LINK
) );
503 cont
->takeValue( RefCountPtr
< const Lang::Value
>
504 ( new Lang::TaggedValue2D( Kernel::THE_ANNOTATION_SYMBOL
, taggedObj
) ),
513 Kernel::registerCore_annotation( Kernel::Environment
* env
)
515 env
->initDefineCoreFunction( new Lang::Core_annotationsite( "site" ) );
516 env
->initDefineCoreFunction( new Lang::Core_annotation_text( "annotationText" ) );
517 env
->initDefineCoreFunction( new Lang::Core_annotation_launch( "annotationLaunch" ) );
518 env
->initDefineCoreFunction( new Lang::Core_annotation_link( "annotationLink" ) );