Update procedures
[shapes.git] / source / coreannotation.cc
blob965226fd98f83cf6da69e11508983963767f9290
1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * any later version.
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008 Henrik Tidefelt
19 #include "Shapes_Helpers_decls.h"
21 #include "shapescore.h"
22 #include "annotations.h"
23 #include "globals.h"
24 #include "shapesexceptions.h"
25 #include "consts.h"
26 #include "simplepdfi.h"
27 #include "simplepdfo.h"
28 #include "tagtypes.h"
29 #include "continuations.h"
30 #include "pagecontentstates.h"
32 #include <iostream>
33 #include <sstream>
35 using namespace Shapes;
37 namespace Shapes
39 namespace Helpers
41 char
42 takeHighlightArgument( const Ast::PlacedIdentifier & calleeId, 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, calleeId, args, i, T::staticTypeName( ) );
56 else
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 )
64 highlight = 'N';
66 else if( *val == HIGHLIGHT_Invert )
68 highlight = 'I';
70 else if( *val == HIGHLIGHT_Outline )
72 highlight = 'O';
74 else if( *val == HIGHLIGHT_Push )
76 highlight = 'P';
78 else
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( )
86 << " }." ;
87 throw Exceptions::CoreOutOfRange( calleeId, args, i, strrefdup( oss ) );
90 return highlight;
96 namespace Shapes
98 namespace Lang
100 class Core_annotationsite : public Lang::CoreFunction
102 public:
103 Core_annotationsite( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name )
104 : CoreFunction( ns, name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), 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 );
138 virtual void
139 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
141 args.applyDefaults( callLoc );
143 size_t argsi = 0;
144 typedef const Lang::Drawable2D TargetType;
145 RefCountPtr< TargetType > target = Helpers::down_cast_CoreArgument< TargetType >( id_, args, argsi, callLoc );
147 ++argsi;
148 typedef const Lang::String ContentTextType;
149 RefCountPtr< ContentTextType > contentTextVal = Helpers::down_cast_CoreArgument< ContentTextType >( id_, args, argsi, callLoc, true );
150 RefCountPtr< const char > contentText = RefCountPtr< const char >( NullPtr< const char >( ) );
151 if( contentTextVal != NullPtr< ContentTextType >( ) )
153 contentText = contentTextVal->val_;
156 ++argsi;
157 typedef const Lang::RGB ColorType;
158 Concrete::RGB color = Helpers::down_cast_CoreArgument< ColorType >( id_, args, argsi, callLoc )->components( );
160 ++argsi;
161 typedef const Lang::String IdentifierType;
162 RefCountPtr< IdentifierType > identifierVal = Helpers::down_cast_CoreArgument< IdentifierType >( id_, args, argsi, callLoc, true );
163 RefCountPtr< const char > identifier = RefCountPtr< const char >( NullPtr< const char >( ) );
164 if( identifierVal != NullPtr< IdentifierType >( ) )
166 identifier = identifierVal->val_;
169 ++argsi;
170 typedef const Lang::Symbol StyleType;
171 RefCountPtr< StyleType > styleVal = Helpers::down_cast_CoreArgument< StyleType >( id_, 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 )
182 borderStyle = 'S';
184 else if( *styleVal == STYLE_Dashed )
186 borderStyle = 'D';
188 else if( *styleVal == STYLE_Beveled )
190 borderStyle = 'B';
192 else if( *styleVal == STYLE_Inset )
194 borderStyle = 'I';
196 else if( *styleVal == STYLE_Underline )
198 borderStyle = 'U';
200 else
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( )
209 << " }." ;
210 throw Exceptions::CoreOutOfRange( id_, args, argsi, strrefdup( oss ) );
214 ++argsi;
215 typedef const Lang::Length WidthType;
216 Concrete::Length width = Helpers::down_cast_CoreArgument< WidthType >( id_, args, argsi, callLoc )->get( );
217 if( width < Concrete::ZERO_LENGTH )
219 throw Exceptions::CoreOutOfRange( id_, args, argsi, "The width must be non-negative." );
222 ++argsi;
223 typedef const Lang::Dash DashType;
224 RefCountPtr< DashType > dash = Helpers::down_cast_CoreArgument< DashType >( id_, args, argsi, callLoc, true );
226 ++argsi;
227 typedef const Lang::Float CloudyType;
228 RefCountPtr< CloudyType > cloudyVal = Helpers::down_cast_CoreArgument< CloudyType >( id_, args, argsi, callLoc, true );
229 double cloudy = -1;
230 if( cloudyVal != NullPtr< CloudyType >( ) )
232 cloudy = cloudyVal->val_;
233 if( cloudy < 0 || cloudy > 2 )
235 throw Exceptions::CoreOutOfRange( id_, args, argsi, "The cloudyness parameter is recommended to lie in the range [ 0, 2 ]." );
239 typedef const Lang::XObject AppearanceType;
240 ++argsi;
241 RefCountPtr< AppearanceType > appearanceNormal = Helpers::down_cast_CoreArgument< AppearanceType >( id_, args, argsi, callLoc, true );
242 ++argsi;
243 RefCountPtr< AppearanceType > appearanceRollover = Helpers::down_cast_CoreArgument< AppearanceType >( id_, args, argsi, callLoc, true );
244 ++argsi;
245 RefCountPtr< AppearanceType > appearanceDown = Helpers::down_cast_CoreArgument< AppearanceType >( id_, args, argsi, callLoc, true );
247 typedef const Lang::Boolean FlagType;
248 size_t flags = 0;
249 ++argsi;
250 if( Helpers::down_cast_CoreArgument< FlagType >( id_, args, argsi, callLoc )->val_ )
252 flags = flags | Lang::AnnotationSite::INVISIBLE;
254 ++argsi;
255 if( Helpers::down_cast_CoreArgument< FlagType >( id_, args, argsi, callLoc )->val_ )
257 flags = flags | Lang::AnnotationSite::HIDDEN;
259 ++argsi;
260 if( Helpers::down_cast_CoreArgument< FlagType >( id_, args, argsi, callLoc )->val_ )
262 flags = flags | Lang::AnnotationSite::PRINT;
264 ++argsi;
265 if( ! Helpers::down_cast_CoreArgument< FlagType >( id_, args, argsi, callLoc )->val_ )
267 flags = flags | Lang::AnnotationSite::NO_ZOOM;
269 ++argsi;
270 if( ! Helpers::down_cast_CoreArgument< FlagType >( id_, args, argsi, callLoc )->val_ )
272 flags = flags | Lang::AnnotationSite::NO_ROTATE;
274 ++argsi;
275 if( ! Helpers::down_cast_CoreArgument< FlagType >( id_, args, argsi, callLoc )->val_ )
277 flags = flags | Lang::AnnotationSite::NO_VIEW;
279 ++argsi;
280 if( ! Helpers::down_cast_CoreArgument< FlagType >( id_, args, argsi, callLoc )->val_ )
282 flags = flags | Lang::AnnotationSite::READ_ONLY;
284 ++argsi;
285 if( Helpers::down_cast_CoreArgument< FlagType >( id_, args, argsi, callLoc )->val_ )
287 flags = flags | Lang::AnnotationSite::LOCKED;
289 ++argsi;
290 if( Helpers::down_cast_CoreArgument< FlagType >( id_, 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 ) ),
300 evalState );
304 class Core_annotation_text : public Lang::CoreFunction
306 public:
307 Core_annotation_text( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name )
308 : CoreFunction( ns, name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), 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 );
318 virtual void
319 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
321 args.applyDefaults( callLoc );
323 size_t argsi = 0;
324 typedef const Lang::AnnotationSite SiteType;
325 RefCountPtr< SiteType > site = Helpers::down_cast_CoreArgument< SiteType >( id_, args, argsi, callLoc );
327 ++argsi;
328 typedef const Lang::String TitleType;
329 RefCountPtr< TitleType > titleVal = Helpers::down_cast_CoreArgument< TitleType >( id_, args, argsi, callLoc, true );
330 RefCountPtr< const char > title = RefCountPtr< const char >( NullPtr< const char >( ) );
331 if( titleVal != NullPtr< TitleType >( ) )
333 title = titleVal->val_;
336 ++argsi;
337 typedef const Lang::Boolean InitiallyOpenType;
338 bool open = Helpers::down_cast_CoreArgument< InitiallyOpenType >( id_, args, argsi, callLoc )->val_;
340 ++argsi;
341 typedef const Lang::Boolean VerifyType;
342 bool verifyIconName = Helpers::down_cast_CoreArgument< VerifyType >( id_, args, argsi, callLoc )->val_;
344 ++argsi;
345 typedef const Lang::String IconType;
346 RefCountPtr< IconType > iconVal = Helpers::down_cast_CoreArgument< IconType >( id_, args, argsi, callLoc, true );
347 RefCountPtr< const char > icon = RefCountPtr< const char >( NullPtr< const char >( ) );
348 if( iconVal != NullPtr< IconType >( ) )
350 icon = iconVal->val_;
351 if( verifyIconName )
353 const char * ptr = icon.getPtr( );
354 if( strcmp( ptr, "Comment" ) == 0 )
356 // OK.
358 else if( strcmp( ptr, "Help" ) == 0 )
360 // OK.
362 else if( strcmp( ptr, "Note" ) == 0 )
364 // OK.
366 else if( strcmp( ptr, "Key" ) == 0 )
368 // OK.
370 else if( strcmp( ptr, "Insert" ) == 0 )
372 // OK.
374 else if( strcmp( ptr, "Paragraph" ) == 0 )
376 // OK.
378 else if( strcmp( ptr, "NewParagraph" ) == 0 )
380 // OK.
382 else
384 throw Exceptions::CoreOutOfRange( id_, 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 ) ),
394 evalState );
398 class Core_annotation_launch : public Lang::CoreFunction
400 public:
401 Core_annotation_launch( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name )
402 : CoreFunction( ns, name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), 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 );
411 virtual void
412 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
414 args.applyDefaults( callLoc );
416 size_t argsi = 0;
417 typedef const Lang::AnnotationSite SiteType;
418 RefCountPtr< SiteType > site = Helpers::down_cast_CoreArgument< SiteType >( id_, args, argsi, callLoc );
420 ++argsi;
421 typedef const Lang::String FilenameType;
422 RefCountPtr< const char > filename = Helpers::down_cast_CoreArgument< FilenameType >( id_, args, argsi, callLoc )->val_;
424 ++argsi;
425 char highlight = Helpers::takeHighlightArgument( id_, args, argsi, callLoc );
427 ++argsi;
428 typedef const Lang::Boolean IsURIType;
429 RefCountPtr< IsURIType > isURIVal = Helpers::down_cast_CoreArgument< IsURIType >( id_, args, argsi, callLoc, true );
430 Lang::LinkAnnotation::Kind kind = Lang::LinkAnnotation::LAUNCH_FILE;
431 if( isURIVal != NullPtr< IsURIType >( ) )
433 if( isURIVal->val_ )
435 kind = Lang::LinkAnnotation::LAUNCH_URI;
437 else
439 kind = Lang::LinkAnnotation::LAUNCH_FILE; // Just in case the default above is changed in the future.
442 else
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;
457 else
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 ) ),
468 evalState );
472 class Core_annotation_link : public Lang::CoreFunction
474 public:
475 Core_annotation_link( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name )
476 : CoreFunction( ns, name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), 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 );
484 virtual void
485 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
487 args.applyDefaults( callLoc );
489 size_t argsi = 0;
490 typedef const Lang::AnnotationSite SiteType;
491 RefCountPtr< SiteType > site = Helpers::down_cast_CoreArgument< SiteType >( id_, args, argsi, callLoc );
493 ++argsi;
494 typedef const Lang::String IdentifierType;
495 RefCountPtr< const char > identifier = Helpers::down_cast_CoreArgument< IdentifierType >( id_, args, argsi, callLoc )->val_;
497 ++argsi;
498 char highlight = Helpers::takeHighlightArgument( id_, 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 ) ),
505 evalState );
512 void
513 Kernel::registerCore_annotation( Kernel::Environment * env )
515 env->initDefineCoreFunction( new Lang::Core_annotationsite( Lang::THE_NAMESPACE_Shapes_Graphics_PDF, "site" ) );
516 env->initDefineCoreFunction( new Lang::Core_annotation_text( Lang::THE_NAMESPACE_Shapes_Graphics_PDF, "annotationText" ) );
517 env->initDefineCoreFunction( new Lang::Core_annotation_launch( Lang::THE_NAMESPACE_Shapes_Graphics_PDF, "annotationLaunch" ) );
518 env->initDefineCoreFunction( new Lang::Core_annotation_link( Lang::THE_NAMESPACE_Shapes_Graphics_PDF, "annotationLink" ) );