Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / annotations.cc
blob0071621ddd5d92cf5ad9c63f96f6ee313eaba764
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 "annotations.h"
22 #include "pdfstructure.h"
23 #include "classtypes.h"
24 #include "drawabletypes.h"
25 #include "pathtypes.h"
26 #include "globals.h"
27 #include "shapesexceptions.h"
29 using namespace Shapes;
32 Lang::AnnotationSite::AnnotationSite( const RefCountPtr< const Lang::Drawable2D > & target, const RefCountPtr< const char > & contentText, const RefCountPtr< const char > & identifier, size_t flags,
33 char borderStyle, const Concrete::Length & borderWidth, const RefCountPtr< const Lang::Dash > & borderDash, double borderCloudy, const Concrete::RGB & color,
34 const RefCountPtr< const Lang::XObject > & appearanceNormal, const RefCountPtr< const Lang::XObject > & appearanceRollover, const RefCountPtr< const Lang::XObject > & appearanceDown )
35 : target_( target ), contentText_( contentText ), identifier_( identifier ), flags_( flags ),
36 borderStyle_( borderStyle ), borderWidth_( borderWidth ), borderDash_( borderDash ), borderCloudy_( borderCloudy ), color_( color ),
37 appearanceNormal_( appearanceNormal ), appearanceRollover_( appearanceRollover ), appearanceDown_( appearanceDown )
38 { }
40 Lang::AnnotationSite::~AnnotationSite( )
41 { }
43 RefCountPtr< const Lang::Class > Lang::AnnotationSite::TypeID( new Lang::SystemFinalClass( strrefdup( "AnnotationSite" ) ) );
44 TYPEINFOIMPL( AnnotationSite );
46 RefCountPtr< const Lang::AnnotationSite >
47 Lang::AnnotationSite::typed_transformed( const Lang::Transform2D & transform ) const
49 return RefCountPtr< const Lang::AnnotationSite >
50 ( new AnnotationSite( target_->typed_transformed( transform, target_ ), contentText_, identifier_, flags_,
51 borderStyle_, borderWidth_, borderDash_, borderCloudy_, color_,
52 appearanceNormal_, appearanceRollover_, appearanceDown_ ) );
55 RefCountPtr< const Lang::Geometric2D >
56 Lang::AnnotationSite::transformed( const Lang::Transform2D & transform, const RefCountPtr< const Lang::Geometric2D > & self ) const
58 return typed_transformed( transform );
61 RefCountPtr< const Lang::Geometric3D >
62 Lang::AnnotationSite::to3D( const RefCountPtr< const Lang::Geometric2D > & self ) const
64 throw Exceptions::NotImplemented( "Annotation sites in 3D." );
67 void
68 Lang::AnnotationSite::gcMark( Kernel::GCMarkedSet & marked )
70 const_cast< Lang::Drawable2D * >( target_.getPtr( ) )->gcMark( marked );
71 if( borderDash_ != NullPtr< const Lang::Dash >( ) )
73 const_cast< Lang::Dash * >( borderDash_.getPtr( ) )->gcMark( marked );
75 if( appearanceNormal_ != NullPtr< const Lang::XObject >( ) )
77 const_cast< Lang::XObject * >( appearanceNormal_.getPtr( ) )->gcMark( marked );
78 } if( appearanceRollover_ != NullPtr< const Lang::XObject >( ) )
80 const_cast< Lang::XObject * >( appearanceRollover_.getPtr( ) )->gcMark( marked );
82 if( appearanceDown_ != NullPtr< const Lang::XObject >( ) )
84 const_cast< Lang::XObject * >( appearanceDown_.getPtr( ) )->gcMark( marked );
88 RefCountPtr< SimplePDF::PDF_Dictionary >
89 Lang::AnnotationSite::getDictionary( const char * subtype, const RefCountPtr< SimplePDF::PDF_Indirect_out > & i_page ) const
91 const SimplePDF::PDF_Version::Version FANCY_VERSION = SimplePDF::PDF_Version::PDF_1_2;
93 RefCountPtr< SimplePDF::PDF_Dictionary > res = RefCountPtr< SimplePDF::PDF_Dictionary >( new SimplePDF::PDF_Dictionary );
95 res->dic[ "Type" ] = SimplePDF::newName( "Annot" );
96 res->dic[ "Subtype" ] = SimplePDF::newName( subtype );
98 Concrete::Coords2D llcorner( 0, 0 );
99 Concrete::Coords2D urcorner( 0, 0 );
100 RefCountPtr< const Lang::ElementaryPath2D > theBBox = target_->bbox( Lang::Drawable2D::BOUNDING );
101 if( theBBox->empty( ) )
103 throw Exceptions::MiscellaneousRequirement( "The annotation target produced an empty bounding box." );
105 theBBox->boundingRectangle( & llcorner, & urcorner );
106 res->dic[ "Rect" ] = RefCountPtr< SimplePDF::PDF_Vector >
107 ( new SimplePDF::PDF_Vector( llcorner.x_.offtype< 1, 0 >( ),
108 llcorner.y_.offtype< 1, 0 >( ),
109 urcorner.x_.offtype< 1, 0 >( ),
110 urcorner.y_.offtype< 1, 0 >( ) ) );
112 if( contentText_ != NullPtr< const char >( ) )
114 res->dic[ "Contents" ] = SimplePDF::newString( contentText_.getPtr( ) );
116 res->dic[ "P" ] = i_page;
117 if( identifier_ != NullPtr< const char >( ) )
119 const SimplePDF::PDF_Version::Version ELEMENT_NAME_VERSION = SimplePDF::PDF_Version::PDF_1_4;
120 if( Kernel::the_PDF_version.greaterOrEqual( ELEMENT_NAME_VERSION ) )
122 res->dic[ "NM" ] = SimplePDF::newString( identifier_.getPtr( ) );
124 else
126 Kernel::the_PDF_version.message( ELEMENT_NAME_VERSION, "Annotation identifiier was ignored." );
129 res->dic[ "F" ] = SimplePDF::newInt( flags_ );
131 RefCountPtr< SimplePDF::PDF_Dictionary > bs = RefCountPtr< SimplePDF::PDF_Dictionary >( new SimplePDF::PDF_Dictionary );
133 if( static_cast< double >( borderWidth_.offtype< 1, 0 >( ) ) != 1 )
135 bs->dic[ "W" ] = SimplePDF::newFloat( borderWidth_.offtype< 1, 0 >( ) );
137 if( borderStyle_ != 'S' )
139 char buf[2];
140 buf[0] = borderStyle_;
141 buf[1] = '\0';
142 bs->dic[ "S" ] = SimplePDF::newName( buf );
144 if( borderDash_ != NullPtr< const Lang::Dash >( ) )
146 bs->dic[ "D" ] = borderDash_->getDashArray( );
148 if( borderCloudy_ >= 0 )
150 RefCountPtr< SimplePDF::PDF_Dictionary > be = RefCountPtr< SimplePDF::PDF_Dictionary >( new SimplePDF::PDF_Dictionary );
151 be->dic[ "S" ] = SimplePDF::newName( "C" );
152 be->dic[ "I" ] = SimplePDF::newFloat( borderCloudy_ );
153 bs->dic[ "BE" ] = be;
156 if( ! bs->dic.empty( ) )
158 if( Kernel::the_PDF_version.greaterOrEqual( FANCY_VERSION ) )
160 res->dic[ "BS" ] = bs;
162 else
164 Kernel::the_PDF_version.message( FANCY_VERSION, "Annotation border style was ignored." );
170 RefCountPtr< SimplePDF::PDF_Dictionary > ap = RefCountPtr< SimplePDF::PDF_Dictionary >( new SimplePDF::PDF_Dictionary );
172 if( appearanceNormal_ != NullPtr< const Lang::XObject >( ) )
174 ap->dic[ "N" ] = appearanceNormal_->getResource( );
176 if( appearanceRollover_ != NullPtr< const Lang::XObject >( ) )
178 ap->dic[ "R" ] = appearanceRollover_->getResource( );
180 if( appearanceDown_ != NullPtr< const Lang::XObject >( ) )
182 ap->dic[ "D" ] = appearanceDown_->getResource( );
185 if( ! ap->dic.empty( ) )
187 if( Kernel::the_PDF_version.greaterOrEqual( FANCY_VERSION ) )
189 res->dic[ "AP" ] = ap;
191 else
193 Kernel::the_PDF_version.message( FANCY_VERSION, "Annotation appearance was ignored." );
198 if( color_.mean( ) > 0 )
200 if( Kernel::the_PDF_version.greaterOrEqual( FANCY_VERSION ) )
202 res->dic[ "C" ] = color_.componentVector( );
204 else
206 Kernel::the_PDF_version.message( FANCY_VERSION, "Annotation color was ignored." );
211 return res;
215 Lang::AnnotationBase::AnnotationBase( const RefCountPtr< const Lang::AnnotationSite > & site )
216 : site_( site )
219 Lang::AnnotationBase::~AnnotationBase( )
222 RefCountPtr< const Lang::Class > Lang::AnnotationBase::TypeID( new Lang::SystemFinalClass( strrefdup( "Annotation" ) ) );
223 TYPEINFOIMPL( AnnotationBase );
225 void
226 Lang::AnnotationBase::gcMark( Kernel::GCMarkedSet & marked )
228 const_cast< AnnotationSite * >( site_.getPtr( ) )->gcMark( marked );
229 this->subtypeGcMark( marked );
233 RefCountPtr< const Lang::Geometric3D >
234 Lang::AnnotationBase::to3D( const RefCountPtr< const Lang::Geometric2D > & self ) const
236 throw Exceptions::NotImplemented( "Annotations in 3D." );
240 Lang::TextAnnotation::TextAnnotation( const RefCountPtr< const Lang::AnnotationSite > & site, const RefCountPtr< const char > & title, bool open, const RefCountPtr< const char > & icon )
241 : Lang::AnnotationBase( site ), title_( title ), open_( open ), icon_( icon )
244 Lang::TextAnnotation::~TextAnnotation( )
247 RefCountPtr< const Lang::Geometric2D >
248 Lang::TextAnnotation::transformed( const Lang::Transform2D & transform, const RefCountPtr< const Lang::Geometric2D > & self ) const
250 return RefCountPtr< const Lang::Geometric2D >
251 ( new TextAnnotation( site_->typed_transformed( transform ), title_, open_, icon_ ) );
254 RefCountPtr< SimplePDF::PDF_Dictionary >
255 Lang::TextAnnotation::getDictionary( const RefCountPtr< SimplePDF::PDF_Indirect_out > & i_page, const std::map< RefCountPtr< const char >, RefCountPtr< SimplePDF::PDF_Vector >, charRefPtrLess > & namedDestinations ) const
257 RefCountPtr< SimplePDF::PDF_Dictionary > res = site_->getDictionary( "Text", i_page );
258 if( title_ != NullPtr< const char >( ) )
260 res->dic[ "T" ] = SimplePDF::newString( title_.getPtr( ) );
262 if( open_ )
264 res->dic[ "Open" ] = SimplePDF::theTrue;
266 if( icon_ != NullPtr< const char >( ) )
268 res->dic[ "Name" ] = SimplePDF::newString( icon_.getPtr( ) );
271 return res;
274 void
275 Lang::TextAnnotation::subtypeGcMark( Kernel::GCMarkedSet & marked )
277 /* Nothing to mark.
282 Lang::LinkAnnotation::LinkAnnotation( const RefCountPtr< const Lang::AnnotationSite > & site, const Ast::SourceLocation & loc, char highlight, const RefCountPtr< const char > & destination, Lang::LinkAnnotation::Kind kind )
283 : Lang::AnnotationBase( site ), loc_( loc ), highlight_( highlight ), destination_( destination ), kind_( kind )
286 Lang::LinkAnnotation::~LinkAnnotation( )
289 RefCountPtr< const Lang::Geometric2D >
290 Lang::LinkAnnotation::transformed( const Lang::Transform2D & transform, const RefCountPtr< const Lang::Geometric2D > & self ) const
292 return RefCountPtr< const Lang::Geometric2D >
293 ( new LinkAnnotation( site_->typed_transformed( transform ), loc_, highlight_, destination_, kind_ ) );
296 RefCountPtr< SimplePDF::PDF_Dictionary >
297 Lang::LinkAnnotation::getDictionary( const RefCountPtr< SimplePDF::PDF_Indirect_out > & i_page, const std::map< RefCountPtr< const char >, RefCountPtr< SimplePDF::PDF_Vector >, charRefPtrLess > & namedDestinations ) const
299 RefCountPtr< SimplePDF::PDF_Dictionary > res = site_->getDictionary( "Link", i_page );
300 if( highlight_ != 'I' )
302 char buf[2];
303 buf[0] = highlight_;
304 buf[1] = '\0';
305 res->dic[ "H" ] = SimplePDF::newName( buf );
308 switch( kind_ )
310 case LAUNCH_FILE:
312 RefCountPtr< SimplePDF::PDF_Dictionary > action = RefCountPtr< SimplePDF::PDF_Dictionary >( new SimplePDF::PDF_Dictionary );
313 res->dic[ "A" ] = action;
314 action->dic[ "S" ] = SimplePDF::newName( "Launch" );
315 action->dic[ "F" ] = SimplePDF::newString( destination_.getPtr( ) );
317 break;
318 case LAUNCH_URI:
320 RefCountPtr< SimplePDF::PDF_Dictionary > action = RefCountPtr< SimplePDF::PDF_Dictionary >( new SimplePDF::PDF_Dictionary );
321 res->dic[ "A" ] = action;
322 action->dic[ "S" ] = SimplePDF::newName( "URI" );
323 action->dic[ "URI" ] = SimplePDF::newString( destination_.getPtr( ) );
324 // RefCountPtr< SimplePDF::PDF_Dictionary > filespec = RefCountPtr< SimplePDF::PDF_Dictionary >( new SimplePDF::PDF_Dictionary );
325 // action->dic[ "F" ] = filespec;
326 // filespec->dic[ "FS" ] = SimplePDF::newName( "URI" );
327 // filespec->dic[ "F" ] = SimplePDF::newString( destination_.getPtr( ) );
329 break;
330 case DOC_LINK:
332 if( namedDestinations.find( destination_ ) == namedDestinations.end( ) )
334 throw new Exceptions::UndefinedCrossRef( loc_, destination_ );
336 res->dic[ "Dest" ] = SimplePDF::newString( destination_.getPtr( ) );
338 break;
339 default:
340 throw Exceptions::InternalError( "Link annotation type out of range." );
343 return res;
346 void
347 Lang::LinkAnnotation::subtypeGcMark( Kernel::GCMarkedSet & marked )
349 /* Nothing to mark.