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 "annotations.h"
22 #include "pdfstructure.h"
23 #include "classtypes.h"
24 #include "drawabletypes.h"
25 #include "pathtypes.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
)
40 Lang::AnnotationSite::~AnnotationSite( )
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." );
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( ) );
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' )
140 buf
[0] = borderStyle_
;
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
;
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
;
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( );
206 Kernel::the_PDF_version
.message( FANCY_VERSION
, "Annotation color was ignored." );
215 Lang::AnnotationBase::AnnotationBase( const RefCountPtr
< const Lang::AnnotationSite
> & site
)
219 Lang::AnnotationBase::~AnnotationBase( )
222 RefCountPtr
< const Lang::Class
> Lang::AnnotationBase::TypeID( new Lang::SystemFinalClass( strrefdup( "Annotation" ) ) );
223 TYPEINFOIMPL( AnnotationBase
);
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( ) );
264 res
->dic
[ "Open" ] = SimplePDF::theTrue
;
266 if( icon_
!= NullPtr
< const char >( ) )
268 res
->dic
[ "Name" ] = SimplePDF::newString( icon_
.getPtr( ) );
275 Lang::TextAnnotation::subtypeGcMark( Kernel::GCMarkedSet
& marked
)
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' )
305 res
->dic
[ "H" ] = SimplePDF::newName( buf
);
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( ) );
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( ) );
332 if( namedDestinations
.find( destination_
) == namedDestinations
.end( ) )
334 throw new Exceptions::UndefinedCrossRef( loc_
, destination_
);
336 res
->dic
[ "Dest" ] = SimplePDF::newString( destination_
.getPtr( ) );
340 throw Exceptions::InternalError( "Link annotation type out of range." );
347 Lang::LinkAnnotation::subtypeGcMark( Kernel::GCMarkedSet
& marked
)