Update suitable examples and tests to use blank mode
[shapes.git] / source / corestate.cc
blob63995186a250ad688b0d8d0386b579d1a26375a0
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, 2009 Henrik Tidefelt
19 #include <cmath>
21 #include "shapescore.h"
22 #include "ast.h"
23 #include "globals.h"
24 #include "shapesexceptions.h"
25 #include "consts.h"
26 #include "simplepdfi.h"
27 #include "pdffunctiontypes.h"
29 #include <iostream>
30 #include <sstream>
31 #include <fstream>
32 #include <vector>
33 #include <stdio.h>
35 using namespace Shapes;
38 namespace Shapes
40 namespace Lang
43 class Core_dashpattern : public Lang::CoreFunction
45 public:
46 Core_dashpattern( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
47 virtual void
48 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
50 RefCountPtr< std::list< Concrete::Length > > pat;
52 if( ! args.empty( ) )
54 Concrete::Length totalLength = 0;
56 typedef const Lang::Length ArgType;
58 for( size_t i = 0;
59 i < args.size( );
60 ++i )
62 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, i, callLoc );
63 if( arg->get( ) < 0 )
65 throw Exceptions::CoreOutOfRange( id_, args, i, "This dashpattern length is negative." );
67 totalLength += arg->get( );
68 pat->push_back( arg->get( ) );
71 if( totalLength == 0 )
73 throw Exceptions::CoreOutOfRange( id_, args, args.size( ) - 1, "The total length of the dashpattern is 0." );
77 Kernel::ContRef cont = evalState->cont_;
78 cont->takeValue( Kernel::ValueRef( new Lang::Dash( pat, 0, 1 ) ),
79 evalState );
83 class Core_noArrow : public Lang::CoreFunction
85 public:
86 Core_noArrow( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
87 virtual void
88 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
90 const size_t ARITY = 1;
91 CHECK_ARITY( args, ARITY, id_ );
93 // We don't even check the type here, even though we could have done so...
95 Kernel::ContRef cont = evalState->cont_;
96 cont->takeValue( Kernel::ValueRef( new Lang::Length( 0 ) ),
97 evalState );
101 class Core_gray : public Lang::CoreFunction
103 public:
104 Core_gray( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
105 virtual void
106 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
108 const size_t ARITY = 1;
109 CHECK_ARITY( args, ARITY, id_ );
111 typedef const Lang::Float ArgType;
112 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
114 if( arg->val_ < 0 )
116 throw Exceptions::CoreOutOfRange( id_, args, 0, "The gray level is less than 0." );
118 if( arg->val_ > 1 )
120 throw Exceptions::CoreOutOfRange( id_, args, 0, "The gray level is greater than 1." );
123 Kernel::ContRef cont = evalState->cont_;
124 cont->takeValue( Kernel::ValueRef( new Lang::Gray( Concrete::Gray( arg->val_ ) ) ),
125 evalState );
129 class Core_rgb : public Lang::CoreFunction
131 public:
132 Core_rgb( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
133 virtual void
134 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
136 const size_t ARITY = 3;
137 CHECK_ARITY( args, ARITY, id_ );
139 double parts[ ARITY ];
141 typedef const Lang::Float ArgType;
142 double * dst( parts );
143 for( size_t i = 0;
144 i < args.size( );
145 ++i, ++dst )
147 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, i, callLoc );
148 if( arg->val_ < 0 )
150 throw Exceptions::CoreOutOfRange( id_, args, i, "This RGB level is less than 0." );
152 if( arg->val_ > 1 )
154 throw Exceptions::CoreOutOfRange( id_, args, i, "This RGB level is greater than 1." );
156 *dst = arg->val_;
159 Kernel::ContRef cont = evalState->cont_;
160 cont->takeValue( Kernel::ValueRef( new Lang::RGB( Concrete::RGB( parts[0], parts[1], parts[2] ) ) ),
161 evalState );
165 class Core_cmyk : public Lang::CoreFunction
167 public:
168 Core_cmyk( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
169 virtual void
170 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
172 const size_t ARITY = 4;
173 CHECK_ARITY( args, ARITY, id_ );
175 double parts[ ARITY ];
177 typedef const Lang::Float ArgType;
178 double * dst( parts );
179 for( size_t i = 0;
180 i < args.size( );
181 ++i, ++dst )
183 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, i, callLoc );
184 if( arg->val_ < 0 )
186 throw Exceptions::CoreOutOfRange( id_, args, i, "This CMYK level is less than 0." );
188 if( arg->val_ > 1 )
190 throw Exceptions::CoreOutOfRange( id_, args, i, "This CMYK level is greater than 1." );
192 *dst = arg->val_;
195 Kernel::ContRef cont = evalState->cont_;
196 cont->takeValue( Kernel::ValueRef( new Lang::CMYK( Concrete::CMYK( parts[0], parts[1], parts[2], parts[3] ) ) ),
197 evalState );
201 class Core_shape : public Lang::CoreFunction
203 public:
204 Core_shape( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
205 virtual void
206 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
208 const size_t ARITY = 1;
209 CHECK_ARITY( args, ARITY, id_ );
211 typedef const Lang::Float ArgType;
212 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
214 if( arg->val_ < 0 )
216 throw Exceptions::CoreOutOfRange( id_, args, 0, "The alpha level is less than 0." );
218 if( arg->val_ > 1 )
220 throw Exceptions::CoreOutOfRange( id_, args, 0, "The alpha level is greater than 1." );
223 Kernel::ContRef cont = evalState->cont_;
224 cont->takeValue( Kernel::ValueRef( new Lang::Alpha( true, arg->val_ ) ),
225 evalState );
229 class Core_opacity : public Lang::CoreFunction
231 public:
232 Core_opacity( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
233 virtual void
234 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
236 const size_t ARITY = 1;
237 CHECK_ARITY( args, ARITY, id_ );
239 typedef const Lang::Float ArgType;
240 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( id_, args, 0, callLoc );
242 if( arg->val_ < 0 )
244 throw Exceptions::CoreOutOfRange( id_, args, 0, "The alpha level is less than 0." );
246 if( arg->val_ > 1 )
248 throw Exceptions::CoreOutOfRange( id_, args, 0, "The alpha level is greater than 1." );
251 Kernel::ContRef cont = evalState->cont_;
252 cont->takeValue( Kernel::ValueRef( new Lang::Alpha( false, arg->val_ ) ),
253 evalState );
257 class Core_alphamask : public Lang::CoreFunction
259 public:
260 Core_alphamask( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name )
261 : CoreFunction( ns, name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
263 formals_->appendEvaluatedCoreFormal( "group", Kernel::THE_SLOT_VARIABLE );
264 formals_->appendEvaluatedCoreFormal( "transform", Kernel::THE_VOID_VARIABLE );
266 virtual void
267 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
269 args.applyDefaults( callLoc );
271 size_t i = 0;
273 typedef const Lang::TransparencyGroup ArgType0;
274 RefCountPtr< ArgType0 > group = Helpers::down_cast_CoreArgument< ArgType0 >( id_, args, i, callLoc );
276 ++i;
277 typedef const Lang::PDF_Function ArgType1;
278 RefCountPtr< ArgType1 > transform = Helpers::down_cast_CoreArgument< ArgType1 >( id_, args, i, callLoc, true );
279 if( transform != NullPtr< ArgType1 >( ) &&
280 ! transform->matchesDimensions( 1, 1 ) )
282 throw Exceptions::CoreOutOfRange( id_, args, i, "The transform function must have dimensions ( 1, 1 )." );
285 Kernel::ContRef cont = evalState->cont_;
286 cont->takeValue( Kernel::ValueRef( new Lang::SoftMask( Lang::SoftMask::ALPHA,
287 group,
288 RefCountPtr< const Lang::Color >( NullPtr< const Lang::Color >( ) ),
289 transform ) ),
290 evalState );
294 class Core_luminositymask : public Lang::CoreFunction
296 public:
297 Core_luminositymask( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name )
298 : CoreFunction( ns, name, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name ), true ) )
300 formals_->appendEvaluatedCoreFormal( "group", Kernel::THE_SLOT_VARIABLE );
301 formals_->appendEvaluatedCoreFormal( "background", Kernel::THE_VOID_VARIABLE );
302 formals_->appendEvaluatedCoreFormal( "transform", Kernel::THE_VOID_VARIABLE );
304 virtual void
305 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
307 args.applyDefaults( callLoc );
309 size_t i = 0;
311 typedef const Lang::TransparencyGroup ArgType0;
312 RefCountPtr< ArgType0 > group = Helpers::down_cast_CoreArgument< ArgType0 >( id_, args, i, callLoc );
313 if( group->colorSpace( )->isInherent( ) )
315 throw Exceptions::CoreOutOfRange( id_, args, i, "The transparency group must not use an inherited blend space." );
318 ++i;
319 typedef const Lang::Color ArgType1;
320 RefCountPtr< ArgType1 > background = Helpers::down_cast_CoreArgument< ArgType1 >( id_, args, i, callLoc, true );
322 ++i;
323 typedef const Lang::PDF_Function ArgType2;
324 RefCountPtr< ArgType2 > transform = Helpers::down_cast_CoreArgument< ArgType2 >( id_, args, i, callLoc, true );
325 if( transform != NullPtr< ArgType2 >( ) &&
326 ! transform->matchesDimensions( 1, 1 ) )
328 throw Exceptions::CoreOutOfRange( id_, args, i, "The transform function must have dimensions ( 1, 1 )." );
331 Kernel::ContRef cont = evalState->cont_;
332 cont->takeValue( Kernel::ValueRef( new Lang::SoftMask( Lang::SoftMask::LUMINOSITY,
333 group,
334 background,
335 transform ) ),
336 evalState );
344 RefCountPtr< const Lang::CoreFunction > Lang::THE_NO_ARROW( new Lang::Core_noArrow( Lang::THE_NAMESPACE_Shapes_Graphics, "NO_ARROW" ) );
346 void
347 Kernel::registerCore_state( Kernel::Environment * env )
349 env->initDefineCoreFunction( new Lang::Core_dashpattern( Lang::THE_NAMESPACE_Shapes_Traits, "dashpattern" ) );
350 env->initDefineCoreFunction( new Lang::Core_gray( Lang::THE_NAMESPACE_Shapes_Traits, "gray" ) );
351 env->initDefineCoreFunction( new Lang::Core_rgb( Lang::THE_NAMESPACE_Shapes_Traits, "rgb" ) );
352 env->initDefineCoreFunction( new Lang::Core_cmyk( Lang::THE_NAMESPACE_Shapes_Traits, "cmyk" ) );
353 env->initDefineCoreFunction( new Lang::Core_shape( Lang::THE_NAMESPACE_Shapes_Traits, "alphashape" ) );
354 env->initDefineCoreFunction( new Lang::Core_opacity( Lang::THE_NAMESPACE_Shapes_Traits, "alphaopacity" ) );
355 env->initDefineCoreFunction( new Lang::Core_alphamask( Lang::THE_NAMESPACE_Shapes_Traits, "alphamask" ) );
356 env->initDefineCoreFunction( new Lang::Core_luminositymask( Lang::THE_NAMESPACE_Shapes_Traits, "luminositymask" ) );