1 /*
2  */
3 
4 /*
5 
6   Copyright (C) 2014 Ferrero Andrea
7 
8   This program is free software: you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation, either version 3 of the License, or
11   (at your option) any later version.
12 
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16   GNU General Public License for more details.
17 
18   You should have received a copy of the GNU General Public License
19   along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21 
22  */
23 
24 /*
25 
26   These files are distributed with PhotoFlow - http://aferrero2707.github.io/PhotoFlow/
27 
28  */
29 
30 #include <string.h>
31 
32 #include "layermanager.hh"
33 #include "image.hh"
34 
35 
36 //#undef NDEBUG
37 
LayerManager(PF::Image * img)38 PF::LayerManager::LayerManager( PF::Image* img ): image( img )
39 {
40 }
41 
42 
~LayerManager()43 PF::LayerManager::~LayerManager()
44 {
45   for(unsigned int i = 0; i < layers_pool.size(); i++) {
46     if(layers_pool[i] == NULL)
47       continue;
48     delete layers_pool[i];
49   }
50 }
51 
52 
new_layer()53 PF::Layer* PF::LayerManager::new_layer()
54 {
55   uint32_t i;
56   for(i = 0; i < layers_pool.size(); i++) {
57     if(layers_pool[i] == NULL) {
58       PF::Layer* l = new PF::Layer(i);
59       l->set_image( image );
60       layers_pool[i] = l;
61       return l;
62     }
63   }
64   PF::Layer* l = new PF::Layer(layers_pool.size());
65   l->set_image( image );
66   layers_pool.push_back(l);
67   return l;
68 }
69 
70 
delete_layer(PF::Layer * layer)71 void PF::LayerManager::delete_layer( PF::Layer* layer )
72 {
73   //  if( layer->get_id() < 0 ) {
74   //    std::cout<<"ERROR: LayerManager::delete_layer(): layer->get_id() < 0"<<std::endl;
75   //    return;
76   //  }
77   if( layer->get_id() >= layers_pool.size() ) {
78     std::cout<<"ERROR: LayerManager::delete_layer(): layer->get_id() >= layers_pool.size()"<<std::endl;
79     return;
80   }
81   layers_pool[layer->get_id()] = NULL;
82 #ifndef NDEBUG
83   std::cout<<"LayerManager::delete_layer(): deleting layer"<<layer<<std::endl;
84 #endif
85   delete layer;
86 }
87 
88 
get_layer(int id)89 PF::Layer* PF::LayerManager::get_layer(int id)
90 {
91   if(id < 0 || id >= (int)layers_pool.size()) return NULL;
92   return ( layers_pool[id] );
93 }
94 
95 
96 
97 // Fills a list with the current layer and all its children
expand_layer(PF::Layer * layer,std::list<PF::Layer * > & list)98 void PF::LayerManager::expand_layer( PF::Layer* layer, std::list<PF::Layer*>& list )
99 {
100   if( !layer ) return;
101   // Sublayers
102 #ifndef NDEBUG
103   std::cout<<"LayerManager::expand_layer: collecting sub-layers of \""<<layer->get_name()<<"\"("<<layer->get_id()<<")"<<std::endl;
104 #endif
105   for( std::list<PF::Layer*>::iterator li = layer->get_sublayers().begin();
106       li != layer->get_sublayers().end(); li++ ) {
107     expand_layer( *li, list);
108   }
109   // Intensity map layers
110 #ifndef NDEBUG
111   std::cout<<"LayerManager::expand_layer: collecting IMAP layers of \""<<layer->get_name()<<"\"("<<layer->get_id()<<")"<<std::endl;
112 #endif
113   for( std::list<PF::Layer*>::iterator li = layer->get_imap_layers().begin();
114       li != layer->get_imap_layers().end(); li++ ) {
115     expand_layer( *li, list);
116   }
117   // Opacity map layers
118 #ifndef NDEBUG
119   std::cout<<"LayerManager::expand_layer: collecting OMAP layers of \""<<layer->get_name()<<"\"("<<layer->get_id()<<")"<<std::endl;
120 #endif
121   for( std::list<PF::Layer*>::iterator li = layer->get_omap_layers().begin();
122       li != layer->get_omap_layers().end(); li++ ) {
123     expand_layer( *li, list);
124   }
125   // the layer itself
126 #ifndef NDEBUG
127   std::cout<<"LayerManager::expand_layer: adding layer \""<<layer->get_name()<<"\"("<<layer->get_id()<<")"<<std::endl;
128 #endif
129   list.push_back( layer );
130 }
131 
132 
get_input_layers(Layer * layer,std::list<PF::Layer * > & container,std::list<Layer * > & inputs)133 void PF::LayerManager::get_input_layers( Layer* layer, std::list<PF::Layer*>& container,
134     std::list<Layer*>& inputs )
135 {
136 #ifndef NDEBUG
137   std::cout<<"Collecting inputs of layer \""<<layer->get_name()<<"\"("<<layer->get_id()<<")"<<std::endl;
138 #endif
139   std::list<PF::Layer*>::iterator li;
140   for(li = container.begin(); li != container.end(); ++li) {
141     PF::Layer* l = *li;
142 #ifndef NDEBUG
143     std::cout<<"  checking layer \""<<l->get_name()<<"\"("<<l->get_id()<<")"<<std::endl;
144 #endif
145     if( l->get_id() == layer->get_id() ) {
146 #ifndef NDEBUG
147     std::cout<<"    reached initial layer, stopping."<<std::endl;
148 #endif
149       break;
150     }
151     // Add layer and all its children to the inputs list
152     expand_layer( l, inputs );
153 #ifndef NDEBUG
154     std::cout<<"    added."<<std::endl;
155 #endif
156   }
157 
158   PF::Layer* container_layer = get_container_layer( layer );
159   if( !container_layer ) return;
160   std::list<PF::Layer*>* clist = get_list( container_layer );
161   if( !clist ) return;
162   get_input_layers( container_layer, *clist, inputs );
163 }
164 
165 
get_input_layers(Layer * layer,std::list<Layer * > & inputs)166 void PF::LayerManager::get_input_layers( Layer* layer, std::list<Layer*>& inputs )
167 {
168   if( !layer ) return;
169   std::list<PF::Layer*>* clist = get_list( layer );
170   if( !clist ) return;
171   get_input_layers( layer, *clist, inputs );
172 }
173 
174 
get_flattened_layers_tree(std::list<Layer * > & inputs)175 void PF::LayerManager::get_flattened_layers_tree( std::list<Layer*>& inputs )
176 {
177   if( layers.empty() ) return;
178   PF::Layer* top_layer = layers.back();
179   if( !top_layer ) return;
180   get_input_layers( top_layer, layers, inputs );
181   //inputs.push_back(top_layer);
182   expand_layer( top_layer, inputs );
183 }
184 
185 
get_child_layers(Layer * layer,std::list<PF::Layer * > & container,std::list<Layer * > & children)186 void PF::LayerManager::get_child_layers( Layer* layer, std::list<PF::Layer*>& container,
187     std::list<Layer*>& children )
188 {
189   PF::Layer* container_layer = get_container_layer( layer );
190 #ifndef NDEBUG
191   std::cout<<"get_child_layers: contaner_layer: \""
192       <<(container_layer ? container_layer->get_name() : "NULL")<<"\""<<std::endl;
193 #endif
194 
195 #ifndef NDEBUG
196   std::cout<<"Collecting children of layer \""<<layer->get_name()<<"\"("<<layer->get_id()<<")"<<std::endl;
197 #endif
198   std::list<PF::Layer*> tmplist, inputs;
199   std::list<PF::Layer*>::reverse_iterator li;
200   // Loop over layers in reverse order and fill a temporary list,
201   // until either the target layer is found or the end of the
202   // container list is reached
203   for(li = container.rbegin(); li != container.rend(); ++li) {
204     PF::Layer* l = *li;
205 #ifndef NDEBUG
206     std::cout<<"  checking layer \""<<l->get_name()<<"\"("<<l->get_id()<<")"<<std::endl;
207 #endif
208     if( l->get_id() == layer->get_id() ) break;
209     // Add layer and all its children to the inputs list,
210     // but only if it is not the container of the target layer.
211     // Otherwise simply add the container layer itself
212     if( l != container_layer) {
213       expand_layer( l, inputs );
214       tmplist.insert( tmplist.begin(), inputs.begin(), inputs.end() );
215     } else {
216       tmplist.push_front( l );
217     }
218 #ifndef NDEBUG
219     std::cout<<"    added."<<std::endl;
220 #endif
221   }
222 
223   // Append the temporary list to the childrens one
224   children.insert( children.end(), tmplist.begin(), tmplist.end() );
225 
226   if( !container_layer ) return;
227 
228   // Add the container layer to the list of children
229   children.push_back( container_layer );
230 
231   std::list<PF::Layer*>* clist = get_list( container_layer );
232 #ifndef NDEBUG
233   std::cout<<"get_child_layers: clist="<<clist<<std::endl;
234 #endif
235   if( !clist ) return;
236 
237   // Add all the children of the container layer to the children list
238   get_child_layers( container_layer, *clist, children );
239 }
240 
241 
get_child_layers(Layer * layer,std::list<Layer * > & children)242 void PF::LayerManager::get_child_layers( Layer* layer, std::list<Layer*>& children )
243 {
244   if( !layer ) return;
245   std::list<PF::Layer*>* clist = get_list( layer );
246   if( !clist ) return;
247   get_child_layers( layer, *clist, children );
248 }
249 
250 /*
251  * Fill the list of layers that are parent of a target layer, i.e. the list of layers
252  * that contribute to the input of the target layer (excluding the mask associated
253  * to the target layer itself)
254  */
get_parent_layers(Layer * layer,std::list<std::pair<std::string,Layer * >> & plist,std::string parent_name,std::list<Layer * > & list)255 bool PF::LayerManager::get_parent_layers(Layer* layer,
256     std::list< std::pair<std::string,Layer*> >& plist,
257     std::string parent_name, std::list<Layer*>& list)
258 {
259 #ifndef NDEBUG
260   std::cout<<"Collecting parents of layer \""<<layer->get_name()
261       <<"\"("<<layer->get_id()<<"), parent_name=\""<<parent_name<<"\""<<std::endl;
262 #endif
263   std::list<PF::Layer*>::iterator li = list.begin();
264   for(li = list.begin(); li != list.end(); ++li) {
265     PF::Layer* l = *li;
266 
267     if( l->get_id() == layer->get_id() )
268       return true;
269 
270     std::string name;
271     if( !parent_name.empty() ) name = parent_name + "/";
272     name = name + l->get_name();
273 #ifndef NDEBUG
274     std::cout<<"  checking layer \""<<l->get_name()<<"\"("<<l->get_id()<<")"<<std::endl;
275 #endif
276 
277     if( get_parent_layers( layer, plist, name, l->sublayers ) )
278       return true;
279 
280     if( l->get_id() != layer->get_id() ) {
281       plist.push_back( make_pair( name, l ) );
282 #ifndef NDEBUG
283       std::cout<<"    added."<<std::endl;
284 #endif
285     }
286 
287     if( layer->is_map() ) {
288       if( get_parent_layers( layer, plist, name+"/IMap/", l->imap_layers ) )
289         return true;
290 
291       if( get_parent_layers( layer, plist, name+"/", l->omap_layers ) )
292         return true;
293     }
294   }
295   return false;
296 }
297 
298 
get_parent_layers(PF::Layer * layer,std::list<std::pair<std::string,PF::Layer * >> & plist)299 void PF::LayerManager::get_parent_layers(PF::Layer* layer,
300     std::list< std::pair<std::string,PF::Layer*> >& plist)
301 {
302   get_parent_layers( layer, plist, std::string(""), layers );
303 }
304 
305 
get_default_input_layer(PF::Layer * layer)306 std::pair< std::pair<int32_t,int32_t>,bool> PF::LayerManager::get_default_input_layer(PF::Layer* layer)
307 {
308   std::pair< std::pair<int32_t,int32_t>,bool> result;
309   result.first.first = -1;
310   result.first.second = 0;
311   result.second = false;
312 
313   if( !image ) return result;
314   PF::Pipeline* pipeline = image->get_pipeline(0);
315   if( !pipeline ) return result;
316   PF::PipelineNode* node = pipeline->get_node(layer);
317   if( !node ) return result;
318   PF::ProcessorBase* proc = node->processor;
319   if( !proc ) return result;
320   PF::OpParBase* par = proc->get_par();
321   if( !par ) return result;
322 
323   std::list< std::pair<std::string,PF::Layer*> > plist;
324   get_parent_layers( layer, plist );
325 
326   PF::Layer* container = get_container_layer(layer);
327   bool is_map = false;
328   if( layer && layer->get_processor() &&
329       layer->get_processor()->get_par() )
330     is_map = layer->get_processor()->get_par()->is_map();
331 
332   std::list< std::pair<std::string,Layer*> >::reverse_iterator iter;
333   for( iter = plist.rbegin(); iter != plist.rend(); iter++ ) {
334     PF::Layer* l = iter->second;
335     if( l == NULL ) continue;
336     if( ! l->is_visible() ) continue;
337     PF::PipelineNode* pnode = pipeline->get_node(l);
338     if( !pnode ) continue;
339     PF::ProcessorBase* pproc = pnode->processor;
340     if( !pproc ) continue;
341     PF::OpParBase* ppar = pproc->get_par();
342     if( !ppar ) continue;
343     colorspace_t cs = ppar->get_colorspace();
344 
345     if( ! par->accepts_colorspace(cs) ) continue;
346 
347     bool is_map2 = false;
348     if( l->get_processor() &&
349         l->get_processor()->get_par() )
350       is_map2 = l->get_processor()->get_par()->is_map();
351 
352     if( is_map ) {
353       std::cout<<"get_default_input_layer: l->get_name()="<<l->get_name()<<"  is_map2="<<is_map2;
354       if( container ) std::cout<<"  container->get_name()="<<container->get_name();
355       else std::cout<<"  container=NULL";
356       std::cout<<std::endl;
357     }
358 
359     if( (container != NULL) && is_map && (!is_map2) ) {
360       // new behavior:
361       // the target is a map layer, while the current layer is not.
362       // In this case we take the output of the container layer before blending as the
363       // input for the mask layer
364       //result.first.first = container->get_id();
365       //result.first.second = 0;
366       //result.second = false;
367       //break;
368 
369       // the target is a map layer, while the current layer is not.
370       // if the container layer has a user-defined input, we take it as default input for the mask.
371       // Otherwise the default input of the container is taken instead.
372       std::cout<<"get_default_input_layer: container->get_inputs().empty()="<<container->get_inputs().empty()<<std::endl;
373       if( !container->get_inputs().empty() )
374         std::cout<<"get_default_input_layer: container->get_inputs()[0].first.first="<<container->get_inputs()[0].first.first<<std::endl;
375       if( container->get_inputs().empty() || (container->get_inputs()[0].first.first < 0) ) {
376         result = get_default_input_layer( container );
377         PF::Layer* rl = get_layer(result.first.first);
378         std::cout<<"get_default_input_layer: result->get_name()="<<(rl?rl->get_name():"")<<std::endl;
379       } else {
380         result = container->get_inputs()[0];
381         PF::Layer* rl = get_layer(result.first.first);
382         std::cout<<"get_default_input_layer: result->get_name()="<<(rl?rl->get_name():"")<<"  blended="<<result.second<<std::endl;
383       }
384       break;
385     }
386 
387     result.first.first = l->get_id();
388     result.first.second = 0;
389     result.second = true;
390     break;
391   }
392 
393   return result;
394 }
395 
396 
397 
get_container_layer(Layer * layer,std::list<Layer * > & list)398 PF::Layer* PF::LayerManager::get_container_layer( Layer* layer, std::list<Layer*>& list )
399 {
400   if( !layer )
401     return NULL;
402 
403   bool is_map = false;
404   if( layer && layer->get_processor() &&
405       layer->get_processor()->get_par() )
406     is_map = layer->get_processor()->get_par()->is_map();
407 
408   // Walk through the list and, for each layer in the list, search for the target layer in the
409   // lists (imaps, omaps and sublayers)
410   std::list<PF::Layer*>::iterator li;
411   for(li = list.begin(); li != list.end(); ++li) {
412     PF::Layer* l = *li;
413     // We first look in the sublayers list
414     std::list<PF::Layer*>::iterator lj;
415     for( lj = l->get_sublayers().begin();
416         lj != l->get_sublayers().end(); ++lj ) {
417       int id1 = layer->get_id();
418       int id2 = ( (*lj)!=NULL ) ? (*lj)->get_id() : -1;
419       if( (*lj) && ((*lj)->get_id() == layer->get_id()) ) {
420         // We found it, no need to continue...
421         return( l );
422       }
423     }
424     if( is_map ) {
425       // If the target layer is a layer map, then we also look into the
426       // intensity and opacity maps
427       std::list<PF::Layer*>::iterator lj;
428       for( lj = l->get_imap_layers().begin();
429           lj != l->get_imap_layers().end(); ++lj ) {
430         int id1 = layer->get_id();
431         int id2 = ( (*lj)!=NULL ) ? (*lj)->get_id() : -1;
432         if( (*lj) && ((*lj)->get_id() == layer->get_id()) ) {
433           // We found it, no need to continue...
434           return( l );
435         }
436       }
437       for( lj = l->get_omap_layers().begin();
438           lj != l->get_omap_layers().end(); ++lj ) {
439         int id1 = layer->get_id();
440         int id2 = ( (*lj)!=NULL ) ? (*lj)->get_id() : -1;
441         if( (*lj) && ((*lj)->get_id() == layer->get_id()) ) {
442           // We found it, no need to continue...
443           return( l );
444         }
445       }
446     }
447   }
448 
449   // If we got here it means that the layer was not found yet, so we
450   // recursively search it in all the sub-layers in the list
451   for(li = list.begin(); li != list.end(); ++li) {
452     PF::Layer* l = *li;
453     PF::Layer* result;
454     result = get_container_layer( layer, l->get_imap_layers() );
455     if( result )
456       return( result );
457     result = get_container_layer( layer, l->get_omap_layers() );
458     if( result )
459       return( result );
460     result = get_container_layer( layer, l->get_sublayers() );
461     if( result )
462       return( result );
463   }
464 
465   // If we reach this point, it means that the layer could not be found...
466   return( NULL );
467 }
468 
get_container_layer(Layer * layer)469 PF::Layer* PF::LayerManager::get_container_layer( Layer* layer )
470 {
471   if( !layer )
472     return( NULL );
473   return( get_container_layer( layer, layers ) );
474 }
475 
get_container_layer(int id)476 PF::Layer* PF::LayerManager::get_container_layer( int id )
477 {
478   PF::Layer* layer = get_layer( id );
479   if( !layer )
480     return( NULL );
481   return( get_container_layer( layer ) );
482 }
483 
484 
485 
get_list(PF::Layer * layer,std::list<PF::Layer * > & list)486 std::list<PF::Layer*>* PF::LayerManager::get_list( PF::Layer* layer, std::list<PF::Layer*>& list)
487 {
488   std::list<PF::Layer*>::iterator li = list.begin();
489   for(li = list.begin(); li != list.end(); ++li) {
490     PF::Layer* l = *li;
491     if( l->get_id() == layer->get_id() ) {
492       return( &list );
493     }
494   }
495 
496   // The layer is not contained in the current list, then we look into sub-lists
497   for(li = list.begin(); li != list.end(); ++li) {
498     PF::Layer* l = *li;
499     std::list<PF::Layer*>* result;
500     result = get_list( layer, l->sublayers );
501     if( result )
502       return result;
503     result = get_list( layer, l->imap_layers );
504     if( result )
505       return result;
506     result = get_list( layer, l->omap_layers );
507     if( result )
508       return result;
509   }
510 
511   return NULL;
512 }
513 
get_list(PF::Layer * layer)514 std::list<PF::Layer*>* PF::LayerManager::get_list(PF::Layer* layer)
515 {
516   return get_list( layer, layers );
517 }
518 
519 
520 
521 
get_cache_buffer()522 PF::CacheBuffer* PF::LayerManager::get_cache_buffer()
523 {
524   return( get_cache_buffer(layers) );
525 }
526 
527 
get_cache_buffer(std::list<Layer * > & list)528 PF::CacheBuffer* PF::LayerManager::get_cache_buffer( std::list<Layer*>& list )
529 {
530   std::list<PF::Layer*>::iterator li = list.begin();
531   for(li = list.begin(); li != list.end(); ++li) {
532     PF::Layer* l = *li;
533 
534     if( !l ) continue;
535     if( !l->is_enabled() ) continue;
536     //std::cout<<"LayerManager::get_cache_buffer(): checking layer "<<l->get_name()<<std::endl;
537 
538     PF::CacheBuffer* buf = NULL;
539     /*
540     for( unsigned int i = 0; i < l->inputs.size(); i++ ) {
541       Layer* lextra = get_layer( l->inputs[i].first );
542       if( lextra && lextra->is_enabled() && lextra->is_cached() && lextra->get_cache_buffer(mode) &&
543           !lextra->get_cache_buffer(mode)->is_completed() ) {
544         buf = lextra->get_cache_buffer( mode );
545 #ifndef NDEBUG
546         std::cout<<"Extra layer #"<<i<<"(\""<<lextra->get_name()<<"\"): pending cache buffer "<<buf<<std::endl;
547 #endif
548         break;
549       }
550     }
551     if( buf ) {
552       std::cout<<"Found pending cache buffer for layer "<<l->get_name<<std::endl;
553       return buf;
554     }
555      */
556 
557     // Now we walk through the intensity and opacity maps to see if they contain a pending buffer
558     buf = get_cache_buffer( l->imap_layers );
559     if( buf ) return buf;
560 
561     buf = get_cache_buffer( l->omap_layers );
562     if( buf ) return buf;
563 
564     // Finally we walk through the sub-layers; again, if re-building is needed
565     // we mark this layer "dirty" as well
566     buf = get_cache_buffer( l->sublayers );
567     if( buf ) return buf;
568 
569     // If the current layer is cached and the cache buffer is not completed, we return it.
570     if( l->get_image() && l->is_cached() && l->get_cache_buffer() &&
571         !l->get_cache_buffer()->is_completed() && l->get_image()->get_npipelines()>CACHE_PIPELINE_ID) {
572       buf = l->get_cache_buffer();
573 #ifndef NDEBUG
574       std::cout<<"Layer \""<<l->get_name()<<"\": pending cache buffer "<<buf<<std::endl;
575       std::cout<<"  l->get_image()->get_npipelines()="<<l->get_image()->get_npipelines()<<std::endl;
576 #endif
577       PF::Pipeline* pipeline = l->get_image()->get_pipeline( CACHE_PIPELINE_ID );
578       //std::cout<<"    l->get_image()->get_pipeline("<<pi<<")->get_render_mode()="
579       //    <<pipeline->get_render_mode()<<std::endl;
580       if( pipeline && pipeline->get_node(l->get_id()) ) {
581         PF::PipelineNode* node = pipeline->get_node(l->get_id());
582         buf->set_image( node->image );
583 #ifndef NDEBUG
584         std::cout<<"Caching layer \""<<l->get_name()<<"\"  image="<<node->image<<std::endl;
585 #endif
586         return( buf );
587       }
588     }
589   }
590   return NULL;
591 }
592 
593 
594 
595 
reset_cache_buffers(bool reinit)596 void PF::LayerManager::reset_cache_buffers( bool reinit )
597 {
598   for(unsigned int i = 0; i < layers_pool.size(); i++) {
599     if(layers_pool[i] == NULL)
600       continue;
601     PF::CacheBuffer* buf = layers_pool[i]->get_cache_buffer();
602     if( buf ) buf->reset( reinit );
603   }
604 }
605 
606 
607 
608 
update_visible(std::list<Layer * > & list,bool parent_visible)609 void PF::LayerManager::update_visible( std::list<Layer*>& list, bool parent_visible )
610 {
611   bool visible;
612   std::list<PF::Layer*>::reverse_iterator li;
613   for(li = list.rbegin(); li != list.rend(); ++li) {
614     PF::Layer* l = *li;
615     if(!l) continue;
616 
617     // Set visible flag to parent value first
618     visible = parent_visible;
619     // Check if current layer is enabled
620     // If not, this and all subsequent and/or child layers
621     // will be marked as invisible
622     if( !l->is_enabled() ) {
623       //std::cout<<"Layer \""<<l->get_name()<<"\" disabled, setting visible flag to false"<<std::endl;
624       visible = false;
625     }
626     l->set_visible( visible );
627     //std::cout<<"Layer \""<<l->get_name()<<"\" visible flag set to "<<visible<<std::endl;
628 
629     // Now we walk through the intensity and opacity maps.
630     update_visible( l->imap_layers, visible );
631 
632     update_visible( l->omap_layers, visible );
633 
634     // Finally we walk through the sub-layers.
635     update_visible( l->sublayers, visible );
636   }
637 }
638 
639 
640 
update_dirty(std::list<Layer * > & list,bool & dirty)641 void PF::LayerManager::update_dirty( std::list<Layer*>& list, bool& dirty )
642 {
643   //if( !list.empty() ) std::cout<<"LayerManager::update_dirty("<<dirty<<")"<<std::endl;
644   std::list<PF::Layer*>::iterator li = list.begin();
645   for(li = list.begin(); li != list.end(); ++li) {
646     PF::Layer* l = *li;
647 
648     bool input_dirty = dirty;
649     bool filter_dirty = false;
650     bool blender_dirty = false;
651 
652     // If the operation associated to the current layer has been modified,
653     // the dirty flag is set to true.
654     // This will also qualify as "dirty" all the subsequent layers in the list
655 #ifndef NDEBUG
656     if( l->get_processor() &&
657         l->get_processor()->get_par() )
658       std::cout<<"  Layer \""<<l->get_name()<<"\": par->is_modified()="
659       <<l->get_processor()->get_par()->is_modified()<<std::endl;
660     if( l->get_blender() &&
661         l->get_blender()->get_par() )
662       std::cout<<"  Layer \""<<l->get_name()<<"\": blender->is_modified()="
663       <<l->get_blender()->get_par()->is_modified()<<std::endl;
664 #endif
665     if( l->get_processor() &&
666         l->get_processor()->get_par() &&
667         l->get_processor()->get_par()->is_modified() )
668       filter_dirty = true;
669 
670     if( l->get_blender() &&
671         l->get_blender()->get_par() &&
672         l->get_blender()->get_par()->is_modified() )
673       blender_dirty = true;
674 
675     // if the current layer is not qualified as "dirty", but one of the extra input layers is,
676     // then we set the dirty flag to true as well
677     for( unsigned int i = 0; i < l->inputs.size(); i++ ) {
678       Layer* lextra = get_layer( l->inputs[i].first.first );
679       if( lextra && lextra->is_dirty() ) {
680         input_dirty = true;
681         break;
682       }
683     }
684 
685     // Now we walk through the intensity and opacity maps to see what needs to be re-built.
686     // If either one or the other has to be re-built, then we mark this layer "dirty" as well
687     bool imap_dirty = false;
688     update_dirty( l->imap_layers, imap_dirty );
689 
690     bool omap_dirty = false;
691     update_dirty( l->omap_layers, omap_dirty );
692 
693     //std::cout<<"  Layer \""<<l->get_name()<<"\": filter_dirty="<<filter_dirty<<" blender_dirty="<<blender_dirty<<" input_dirty="<<input_dirty<<" imap_dirty="<<imap_dirty<<" omap_dirty="<<omap_dirty<<std::endl;
694 
695     if( imap_dirty )
696       input_dirty = true;
697 
698     if( omap_dirty )
699       blender_dirty = true;
700 
701     // Finally we walk through the sub-layers; again, if re-building is needed
702     // we mark this layer "dirty" as well
703     bool sub_dirty = dirty;
704     update_dirty( l->sublayers, sub_dirty );
705 
706     //std::cout<<"  Layer \""<<l->get_name()<<"\": sub_dirty="<<sub_dirty<<std::endl;
707 
708     if( sub_dirty )
709       input_dirty = true;
710 
711     //std::cout<<"  Layer \""<<l->get_name()<<"\": dirty="<<dirty
712     //         <<" l->is_dirty()="<<l->is_dirty()<<std::endl;
713     // if the current layer is dirty the dirty flag is set to true
714     // this will also qualify as "dirty" all the subsequent layers in the list
715     // It probably means that the visibility of the layer has been toggled
716     if( l->is_dirty() )
717       dirty = true;
718 
719     dirty = dirty || input_dirty || blender_dirty || filter_dirty;
720 
721     // Now we have finished walking through all the subchains and extra inputs,
722     // and we can set the dirty flag for the current layer
723     //if( dirty ) {
724     //  std::cout<<"  Layer \""<<l->get_name()<<"\"->is_dirty()="<<l->is_dirty()<<std::endl;
725     //  std::cout<<"  Layer \""<<l->get_name()<<"\"->set_dirty("<<dirty<<")"<<std::endl;
726     //}
727     l->set_dirty( dirty );
728 
729     // we mark the operations as "modified" if their input data
730     // has changed, so that they will be re-built
731     if( input_dirty && l->get_processor() &&
732         l->get_processor()->get_par() ) {
733       l->get_processor()->get_par()->set_modified();
734     }
735     if( (input_dirty || blender_dirty || filter_dirty) &&
736         l->get_blender() && l->get_blender()->get_par() ) {
737       l->get_blender()->get_par()->set_modified();
738     }
739 
740     // If the current layer is cached, we reset the corresponding cache buffer
741     // so that the computation will restart from scratch at the next idle loop
742     if( /*l->is_dirty() ||*/ input_dirty || filter_dirty ) {
743       if( l->is_cached() )
744         l->reset_cache_buffers();
745       //if( l->is_cached() && l->get_cache_buffer() ) l->get_cache_buffer()->reset();
746     }
747   }
748 }
749 
750 
751 
752 
set_layers_dirty_flag(std::list<Layer * > & list)753 void PF::LayerManager::set_layers_dirty_flag( std::list<Layer*>& list )
754 {
755   std::list<PF::Layer*>::iterator li = list.begin();
756   for(li = list.begin(); li != list.end(); ++li) {
757     PF::Layer* l = *li;
758 
759     if( l->get_processor() &&
760         l->get_processor()->get_par() )
761       l->get_processor()->get_par()->clear_modified();
762     if( l->get_blender() &&
763         l->get_blender()->get_par() )
764       l->get_blender()->get_par()->clear_modified();
765 
766     l->set_dirty(true);
767 
768     set_layers_dirty_flag( l->imap_layers );
769     set_layers_dirty_flag( l->omap_layers );
770     set_layers_dirty_flag( l->sublayers );
771   }
772 }
773 
774 
775 
776 
reset_layers_dirty_flag(std::list<Layer * > & list)777 void PF::LayerManager::reset_layers_dirty_flag( std::list<Layer*>& list )
778 {
779   std::list<PF::Layer*>::iterator li = list.begin();
780   for(li = list.begin(); li != list.end(); ++li) {
781     PF::Layer* l = *li;
782 
783     if( l->get_processor() &&
784         l->get_processor()->get_par() )
785       l->get_processor()->get_par()->clear_modified();
786     if( l->get_blender() &&
787         l->get_blender()->get_par() )
788       l->get_blender()->get_par()->clear_modified();
789 
790     l->clear_dirty();
791 
792     reset_layers_dirty_flag( l->imap_layers );
793     reset_layers_dirty_flag( l->omap_layers );
794     reset_layers_dirty_flag( l->sublayers );
795   }
796 }
797 
798 
799 
800 
init_pipeline(PF::Pipeline * pipeline,std::list<Layer * > & list,PF::Layer * previous_layer)801 void PF::LayerManager::init_pipeline( PF::Pipeline* pipeline, std::list<Layer*>& list, PF::Layer* previous_layer )
802 {
803   std::list<PF::Layer*>::iterator li = list.begin();
804   for(li = list.begin(); li != list.end(); ++li) {
805     PF::Layer* l = *li;
806 
807     if( !l ) continue;
808 #ifndef NDEBUG
809     std::cout<<"LayerManager::init_pipeline(): adding layer \""
810         <<l->get_name()<<"\""<<std::endl;
811 #endif
812     // Detect "pathological" conditions
813     g_assert( l->get_processor() != NULL );
814     g_assert( l->get_processor()->get_par() != NULL );
815     g_assert( l->get_blender() != NULL );
816     g_assert( l->get_blender()->get_par() != NULL );
817 
818     // Create the node if it does not yet exist, and copy the parameters
819     // from the operation associated with the layer to the
820     // operation associated with the node
821     PF::PipelineNode* node = pipeline->set_node( l, previous_layer );
822     g_assert( node != NULL );
823     g_assert( node->processor != NULL );
824     g_assert( node->processor->get_par() != NULL );
825     g_assert( node->blender != NULL );
826     g_assert( node->blender->get_par() != NULL );
827 
828     PF::OpParBase* par = l->get_processor()->get_par();
829     PF::OpParBase* pipelinepar = node->processor->get_par();
830     PF::OpParBase* blender = l->get_blender()->get_par();
831     PF::OpParBase* pipelineblender = node->blender->get_par();
832 
833     // Run pre-build phase
834 #ifndef NDEBUG
835     std::cout<<"LayerManager::init_pipeline(): calling pre_build() for layer \""
836         <<l->get_name()<<"\""<<std::endl;
837 #endif
838     par->pre_build( pipeline->get_render_mode() );
839 
840     // We import the parameters from the "master" operation associated to the layer,
841     // and which is directly connected with the GUI controls
842     //std::cout<<"LayerManager::init_pipeline(): calling import_settings() for layer \""
843     //    <<l->get_name()<<"\""<<std::endl;
844     pipelinepar->import_settings( par );
845     pipelineblender->import_settings( blender );
846     //std::cout<<"  settings imported."<<std::endl;
847 
848     pipelinepar->set_output_caching( pipeline->get_op_caching_enabled() );
849     pipelineblender->set_output_caching( pipeline->get_op_caching_enabled() );
850 
851     init_pipeline( pipeline, l->imap_layers, NULL );
852     init_pipeline( pipeline, l->omap_layers, NULL );
853     init_pipeline( pipeline, l->sublayers, previous_layer );
854 
855     previous_layer = l;
856   }
857 }
858 
859 
860 
861 
update_ui(std::list<Layer * > & list)862 void PF::LayerManager::update_ui( std::list<Layer*>& list )
863 {
864   std::list<PF::Layer*>::iterator li = list.begin();
865   for(li = list.begin(); li != list.end(); ++li) {
866     PF::Layer* l = *li;
867 
868     if( l->get_processor() &&
869         l->get_processor()->get_par() &&
870         l->get_processor()->get_par()->get_config_ui() ) {
871       l->get_processor()->get_par()->get_config_ui()->update();
872     }
873     update_ui( l->imap_layers );
874     update_ui( l->omap_layers );
875     update_ui( l->sublayers );
876   }
877 }
878 
879 
880 
881 
update_ui()882 void PF::LayerManager::update_ui()
883 {
884   update_ui( layers );
885 }
886 
887 
888 
889 
reset_op_caching(PF::Pipeline * pipeline)890 void PF::LayerManager::reset_op_caching( PF::Pipeline* pipeline )
891 {
892   if( !pipeline || !(pipeline->get_op_caching_enabled()) ) return;
893   reset_op_caching(pipeline, layers);
894 }
895 
896 
reset_op_caching(PF::Pipeline * pipeline,std::list<Layer * > & list)897 void PF::LayerManager::reset_op_caching( PF::Pipeline* pipeline, std::list<Layer*>& list )
898 {
899   std::list<PF::Layer*>::iterator li = list.begin();
900   for(li = list.begin(); li != list.end(); ++li) {
901     PF::Layer* l = *li;
902 
903     if( !l ) continue;
904     if( !l->is_enabled() ) continue;
905     //std::cout<<"LayerManager::get_cache_buffer(): checking layer "<<l->get_name()<<std::endl;
906 
907     reset_op_caching( pipeline, l->imap_layers );
908 
909     reset_op_caching( pipeline, l->omap_layers );
910 
911     // Finally we walk through the sub-layers
912     reset_op_caching( pipeline, l->sublayers );
913 
914     //for( unsigned int pi = 0; pi < l->get_image()->get_npipelines(); pi++ ) {
915     //  PF::Pipeline* pipeline = l->get_image()->get_pipeline( pi );
916     //  if( !pipeline || !(pipeline->get_op_caching_enabled()) ) continue;
917 
918       PF::PipelineNode* node = pipeline->get_node(l->get_id());
919       if( !node ) continue;
920       if( !node->processor ) continue;
921       if( !node->processor->get_par() ) continue;
922       node->processor->get_par()->reset_output_padding();
923       if( !node->blender ) continue;
924       if( !node->blender->get_par() ) continue;
925       node->blender->get_par()->reset_output_padding();
926     //}
927   }
928 }
929 
930 
931 
932 
update_op_caching(PF::Pipeline * pipeline)933 void PF::LayerManager::update_op_caching( PF::Pipeline* pipeline )
934 {
935   //if( !pipeline || !(pipeline->get_op_caching_enabled()) ) return;
936   if( !pipeline ) return;
937 
938   reset_op_caching( pipeline );
939 
940   //std::cout<<std::endl<<"LayerManager::update_op_caching():"<<std::endl;
941   update_op_caching( pipeline, layers, NULL );
942 }
943 
944 
945 
946 
update_op_caching(PF::Pipeline * pipeline,std::list<Layer * > & list,PF::Layer * input)947 void PF::LayerManager::update_op_caching( PF::Pipeline* pipeline, std::list<Layer*>& list, PF::Layer* input )
948 {
949   PF::Pipeline* pipeline0 = get_image()->get_pipeline( 0 );
950   //if( pipeline == pipeline0 ) return;
951 
952   //std::cout<<"LayerManager::update_op_caching() called for layer \""
953   //    <<(input ? input->get_name() : "NULL")<<"\""<<std::endl;
954 
955   std::list<PF::Layer*>::reverse_iterator li;
956   for(li = list.rbegin(); li != list.rend(); ++li) {
957     PF::Layer* l = *li;
958     if(!l) continue;
959     if(!l->is_visible()) continue;
960 
961     PF::PipelineNode* node0 = pipeline0->get_node(l->get_id());
962     if( !node0 ) continue;
963     if( !node0->image ) continue;
964 
965     PF::PipelineNode* node = pipeline->get_node(l->get_id());
966     if( !node ) continue;
967     if( !node->processor ) continue;
968     if( !node->processor->get_par() ) continue;
969     PF::OpParBase* par = node->processor->get_par();
970 
971     //std::cout<<"  calling compute_padding() for layer: \""<<l->get_name()<<std::endl;
972     par->compute_padding( node0->image, 0, pipeline->get_level() );
973     int padding = par->get_padding(0);
974 
975     //std::cout<<"  current layer: \""<<l->get_name()<<"\", padding="<<padding<<std::endl;
976 
977     PF::PipelineNode* pnode0 = NULL;
978     PF::PipelineNode* pnode = NULL;
979     PF::OpParBase* ppar = NULL;
980     std::list<PF::Layer*>::reverse_iterator lj = li; ++lj;
981     PF::Layer* lprev = NULL;
982     for( ; lj != list.rend(); ++lj ) {
983       lprev = *lj;
984       if(!lprev) continue;
985       if(!lprev->is_visible()) continue;
986 
987       pnode0 = pipeline0->get_node(lprev->get_id());
988       if( !pnode0 ) continue;
989 
990       pnode = pipeline->get_node(lprev->get_id());
991       if( !pnode ) continue;
992       if( !pnode->processor ) continue;
993       if( !pnode->blender ) continue;
994       if( !pnode->processor->get_par() ) continue;
995       if( !pnode->blender->get_par() ) continue;
996       ppar = pnode->processor->get_par();
997 
998       // for the moment we keep the logic simple:
999       // if the operation allows opacity blending, we cache the blender
1000       // output instead of the operation output
1001       if( ppar->has_opacity() ) {
1002         ppar = pnode->blender->get_par();
1003       }
1004 
1005       // check if the current operation is a mere transfer of images
1006       // currently only buffer layers fall under this category
1007       // in the NoOp case we walk one step more down the hierarchy
1008       bool is_noop = ppar->is_noop( pnode0->image, 0, pipeline->get_level() );
1009       //std::cout<<"    layer: \""<<lprev->get_name()<<"\", is_noop="<<is_noop<<std::endl;
1010       if( !is_noop ) break;
1011     }
1012     if( !lprev ) {
1013       lprev = input;
1014       if( lprev ) {
1015         pnode0 = pipeline0->get_node(lprev->get_id());
1016         if( !pnode0 ) continue;
1017 
1018         pnode = pipeline->get_node(lprev->get_id());
1019         if( !pnode ) continue;
1020         if( !pnode->processor ) continue;
1021         if( !pnode->blender ) continue;
1022         if( !pnode->processor->get_par() ) continue;
1023         if( !pnode->blender->get_par() ) continue;
1024         ppar = pnode->processor->get_par();
1025 
1026         // for the moment we keep the logic simple:
1027         // if the operation allows opacity blending, we cache the blender
1028         // output instead of the operation output
1029         if( ppar->has_opacity() ) {
1030           ppar = pnode->blender->get_par();
1031         }
1032 
1033         // check if the current operation is a mere transfer of images
1034         // currently only buffer layers fall under this category
1035         // in the NoOp case we walk one step more down the hierarchy
1036         bool is_noop = ppar->is_noop( pnode0->image, 0, pipeline->get_level() );
1037         if( is_noop ) { lprev = NULL; ppar = NULL; }
1038       }
1039     }
1040 
1041     //if( lprev ) std::cout<<"    previous layer: \""<<(lprev ? lprev->get_name() : "NULL")<<"\""<<std::endl;
1042 
1043 
1044     // Once more, we keep this preliminary implementation simple, and we ignore
1045     // the case where an operation oututs more than one image
1046     // currently only the wavelet decomposition tool does it
1047     if( padding > 0 && lprev && ppar ) {
1048       ppar->set_output_padding( padding, 0 );
1049 #ifndef NDEBUG
1050       std::cout<<"      ppar->get_output_padding(0)="<<ppar->get_output_padding(0)
1051           <<"  ppar->get_output_caching()="<<ppar->get_output_caching()<<std::endl;
1052 #endif
1053     }
1054 
1055     if( !(l->get_sublayers().empty()) ) {
1056       //std::cout<<"  updating sub-layers of layer \""<<l->get_name()<<"\""<<std::endl;
1057       update_op_caching( pipeline, l->get_sublayers(), lprev );
1058     }
1059 
1060     if( !(l->get_imap_layers().empty()) ) {
1061       update_op_caching( pipeline, l->get_imap_layers(), NULL );
1062     }
1063 
1064     if( !(l->get_omap_layers().empty()) ) {
1065       //std::cout<<"  updating mask layers of layer \""<<l->get_name()<<"\""<<std::endl;
1066       update_op_caching( pipeline, l->get_omap_layers(), NULL );
1067     }
1068   }
1069 }
1070 
1071 
1072 
1073 
insert_layer(std::list<Layer * > & layers,Layer * layer,int32_t lid)1074 bool PF::insert_layer( std::list<Layer*>& layers, Layer* layer, int32_t lid )
1075 {
1076   if( lid < 0 ) {
1077     layers.push_back( layer );
1078     return true;
1079   }
1080 
1081   std::list<Layer*>::iterator it;
1082   for( it = layers.begin(); it != layers.end(); ++it )
1083     if( (int32_t)(*it)->get_id() == lid ) break;
1084 
1085   if( it == layers.end() ) return false;
1086   it++;
1087   layers.insert( it, layer );
1088 
1089   return true;
1090 }
1091 
1092 
1093 
insert_layer(Layer * layer,int32_t lid)1094 bool PF::LayerManager::insert_layer( Layer* layer, int32_t lid )
1095 {
1096   return PF::insert_layer( layers, layer, lid );
1097 }
1098 
1099 
remove_layer(PF::Layer * layer)1100 bool PF::LayerManager::remove_layer( PF::Layer* layer )
1101 {
1102   if( layer == NULL ) return false;
1103 
1104   // Get the container list
1105   std::list<Layer*>* list = get_list( layer );
1106   if( list == NULL ) return false;
1107 
1108   // Iterate over the list to find the good one
1109   std::list<Layer*>::iterator it;
1110   for( it = list->begin(); it != list->end(); ++it ) {
1111     if( (*it) == layer ) {
1112       list->erase( it );
1113       return true;
1114     }
1115   }
1116 
1117   return false;
1118 }
1119 
1120 
1121 
1122 
rebuild_chain(PF::Pipeline * pipeline,colorspace_t cs,int width,int height,std::list<PF::Layer * > & list,PF::Layer * previous_layer)1123 VipsImage* PF::LayerManager::rebuild_chain( PF::Pipeline* pipeline, colorspace_t cs,
1124     int width, int height,
1125     std::list<PF::Layer*>& list,
1126     PF::Layer* previous_layer )
1127 {
1128   PipelineNode* previous_node = NULL;
1129   VipsImage* previous = NULL;
1130 
1131   VipsImage* out = NULL;
1132   std::list<PF::Layer*>::iterator li = list.begin();
1133   for(li = list.begin(); li != list.end(); ++li) {
1134     PF::Layer* l = *li;
1135 
1136     // Detect "pathological" conditions
1137     g_assert( l->get_processor() != NULL );
1138     g_assert( l->get_processor()->get_par() != NULL );
1139     g_assert( l->get_blender() != NULL );
1140     g_assert( l->get_blender()->get_par() != NULL );
1141 
1142     char* name = (char*)l->get_name().c_str();
1143     if( !l->is_enabled() ) continue;
1144 
1145 #ifndef NDEBUG
1146     std::cout<<"PF::LayerManager::rebuild_chain(): processing layer \""<<name<<"\""<<std::endl;
1147     std::cout<<"                                   is_modified: "<<l->is_modified()<<std::endl;
1148     std::cout<<"                                   is_dirty: "<<l->is_dirty()<<std::endl;
1149 #endif
1150     if( previous_layer ) {
1151       previous_node = pipeline->get_node( previous_layer->get_id() );
1152       //if( previous_node ) previous = previous_node->image;
1153       if( previous_node ) previous = previous_node->blended;
1154 #ifndef NDEBUG
1155       std::cout<<"  Previous layer: \""<<previous_layer->get_name()<<"\""<<std::endl;
1156 #endif
1157     }
1158 
1159     // Create the node if it does not yet exist, and copy the parameters
1160     // from the operation associated with the layer to the
1161     // operation associated with the node
1162     PF::PipelineNode* node = pipeline->set_node( l, previous_layer );
1163     g_assert( node != NULL );
1164     g_assert( node->processor != NULL );
1165     g_assert( node->processor->get_par() != NULL );
1166     g_assert( node->blender != NULL );
1167     g_assert( node->blender->get_par() != NULL );
1168 
1169     PF::OpParBase* par = l->get_processor()->get_par();
1170     PF::OpParBase* pipelinepar = node->processor->get_par();
1171     PF::OpParBase* blender = l->get_blender()->get_par();
1172     PF::OpParBase* pipelineblender = node->blender->get_par();
1173 
1174     //l->set_cached( par->needs_caching() );
1175 
1176 #ifndef NDEBUG
1177     std::cout<<"PF::LayerManager::rebuild_chain(): setting format for layer "<<l->get_name()
1178                        <<" to "<<pipeline->get_format()<<std::endl;
1179     std::cout<<"  pipelinepar->set_render_mode( "<<pipeline->get_render_mode()<<" );"<<std::endl;
1180 #endif
1181     pipelinepar->set_format( pipeline->get_format() );
1182     pipelinepar->set_render_mode( pipeline->get_render_mode() );
1183 
1184 #ifndef NDEBUG
1185     std::cout<<"PF::LayerManager::rebuild_chain(): par->is_modified()="<<par->is_modified()
1186             <<"  blender->is_modified()="<<blender->is_modified()
1187             <<"  node->image="<<node->image<<"  pipeline->get_force_rebuild()="<<pipeline->get_force_rebuild()<<std::endl;
1188 #endif
1189     if( true && !pipeline->get_force_rebuild() && !par->is_modified() && (node->image != NULL) ) {
1190       // If the current operation is not modified, we check if the blender was modified
1191 #ifndef NDEBUG
1192       std::cout<<"LayerManager::rebuild_chain(): reusing existing layer \""<<l->get_name()
1193               <<"\" node->image="<<node->image<<std::endl;
1194 #endif
1195       VipsImage* blendedimg = node->blended;
1196       if( node->image && blender->is_modified() ) {
1197         // if the blender was modified we rebuild the blended image using the existing
1198         // output of the current operation
1199         if( par->has_opacity() && blender && pipelineblender) {
1200 #ifndef NDEBUG
1201           std::cout<<"LayerManager::rebuild_chain(): rebuilding blender output for layer \""<<l->get_name()
1202                   <<"\""<<std::endl;
1203 #endif
1204           if( node->blended ) {
1205             std::cout<<"LayerManager::rebuild_chain(): vips_image_invalidate_all() called on node->blended"<< std::endl;
1206             vips_image_invalidate_all( node->blended );
1207           }
1208 
1209           unsigned int level = pipeline->get_level();
1210           //pipelineblender->import_settings( blender );
1211 
1212           VipsImage* omap = NULL;
1213           if( previous && !l->omap_layers.empty() && pipelineblender->get_mask_enabled()==true ) {
1214             omap = rebuild_chain( pipeline, PF_COLORSPACE_GRAYSCALE,
1215                 previous->Xsize, previous->Ysize,
1216                 l->omap_layers, NULL );
1217           }
1218 
1219           std::vector<VipsImage*> in;
1220           // we add the previous image to the list of inputs, even if it is NULL
1221           in.push_back( previous );
1222           in.push_back( node->image );
1223           blendedimg = pipelineblender->build( in, 0, NULL, omap, level );
1224 #ifndef NDEBUG
1225           if(blendedimg)
1226             std::cout<<"rebuild_chain(): Layer \""<<l->get_name()<<"\" level="<<level
1227             <<"  blended size: "<<blendedimg->Xsize<<","<<blendedimg->Ysize<<std::endl;
1228 #endif
1229         } else {
1230           blendedimg = node->image;
1231           PF_REF(blendedimg,"LayerManager::rebuild_chain(): blendedimg ref");
1232         }
1233 #ifndef NDEBUG
1234         std::cout<<"rebuild_chain(): Layer \""<<l->get_name()<<"\"  blended: "<<blendedimg<<std::endl;
1235 #endif
1236         pipeline->set_blended( blendedimg, l->get_id() );
1237       }
1238       out = blendedimg;
1239       //previous = newimg;
1240       previous_layer = l;
1241       if(pipelineblender) pipelineblender->clear_modified();
1242       continue;
1243     }
1244 
1245 #ifndef NDEBUG
1246     std::cout<<"LayerManager::rebuild_chain(): rebuilding output for layer \""<<l->get_name()
1247                           <<"\""<<std::endl;
1248 #endif
1249     if( node->image ) {
1250 #ifndef NDEBUG
1251       std::cout<<"LayerManager::rebuild_chain(): vips_image_invalidate_all() called on node->image"<< std::endl;
1252 #endif
1253       vips_image_invalidate_all( node->image );
1254     }
1255     //if( node->blended ) vips_image_invalidate_all( node->blended );
1256 
1257     // Run pre-build phase
1258     //par->pre_build( pipeline->get_render_mode() );
1259 
1260     PF::PropertyBase* p_rgb_target_ch =  blender->get_property( "rgb_target_channel" );
1261     if( p_rgb_target_ch )
1262       p_rgb_target_ch->set_enum_value( par->get_rgb_target_channel() );
1263     PF::PropertyBase* p_lab_target_ch =  blender->get_property( "lab_target_channel" );
1264     if( p_lab_target_ch )
1265       p_lab_target_ch->set_enum_value( par->get_lab_target_channel() );
1266     PF::PropertyBase* p_cmyk_target_ch = blender->get_property( "cmyk_target_channel" );
1267     if( p_cmyk_target_ch )
1268       p_cmyk_target_ch->set_enum_value( par->get_cmyk_target_channel() );
1269 
1270 #ifndef NDEBUG
1271     std::cout<<"PF::LayerManager::rebuild_chain(): setting format for layer "<<l->get_name()
1272                        <<" to "<<pipeline->get_format()<<std::endl;
1273 #endif
1274     pipelineblender->set_format( pipeline->get_format() );
1275     pipelineblender->set_render_mode( pipeline->get_render_mode() );
1276 
1277     // If the layer is at the beginning of the chain, we set hints about the desired
1278     // colorspace and pixel format using default values.
1279     // The size and colorspace hints might be ignored by
1280     // the operation (for example in the case of an image from a file, where the
1281     // size and colorspace are dictated by the file content).
1282     // On the other hand, the pixel format hint should be strictly respected by all
1283     // operators, as it defined the accuracy at which the final image is rendered.
1284     // If a previous image has been created already, hints are copied from it.
1285     //if( li == list.begin() || !previous )
1286     if( !previous ) {
1287       pipelinepar->set_image_hints( width, height, cs );
1288       pipelineblender->set_image_hints( width, height, cs );
1289     } else {
1290       pipelinepar->set_image_hints( previous );
1291       pipelineblender->set_image_hints( previous );
1292     }
1293     //PF::colorspace_t cs = PF::convert_colorspace( pipelinepar->get_interpretation() );
1294     //std::cout<<"  par: "<<pipelinepar<<std::endl;
1295     //std::cout<<"  cs after set_image_hints: "<<cs<<std::endl;
1296 
1297     /* At this point there are two possibilities:
1298        1. the layer has no sub-layers, in which case it is combined with the output
1299        of the previous layer plus any extra inputs it might have
1300        2. the layer has sub-layers, in which case we first build the sub-layers chain
1301        and then we combine it with the output of the previous layer
1302      */
1303     VipsImage* newimg = NULL;
1304     std::vector<VipsImage*> newimgvec;
1305     VipsImage* imap = NULL;
1306     VipsImage* omap = NULL;
1307     if( l->sublayers.empty() ) {
1308       std::vector<VipsImage*> in;
1309 #ifndef NDEBUG
1310       std::cout<<"Layer \""<<l->get_name()<<"\""
1311           <<"  par->needs_input()="<<par->needs_input()
1312           <<"  previous="<<previous
1313           <<"  get_previous_layer_is_input="<<par->get_previous_layer_is_input()
1314           <<"  l->inputs.size()="<<l->inputs.size()
1315           <<std::endl;
1316 #endif
1317       if( false && par->needs_input() && !previous && l->inputs.empty() ) {
1318         // Here we have a problem: the operation we are trying to insert in the chain requires
1319         // a primary input image, but there is no previous image available... we give up
1320         std::cout<<"LayerManager::rebuild_chain(): missing input data for layer \""<<l->get_name()<<"\""<<std::endl;
1321         return NULL;
1322       }
1323 
1324       // We build the chains for the intensity and opacity maps
1325 #ifndef NDEBUG
1326       std::cout<<"Layer \""<<l->get_name()<<"\""
1327           <<"  imap_layers.size()="<<l->imap_layers.size()
1328           <<"  omap_layers.size()="<<l->omap_layers.size()
1329           <<std::endl;
1330 #endif
1331       if( previous && !l->imap_layers.empty() && pipelinepar->get_mask_enabled()==true ) {
1332         imap = rebuild_chain( pipeline, PF_COLORSPACE_GRAYSCALE,
1333             previous->Xsize, previous->Ysize,
1334             l->imap_layers, NULL );
1335       }
1336 
1337       if( previous && !l->omap_layers.empty() && pipelineblender->get_mask_enabled()==true ) {
1338         omap = rebuild_chain( pipeline, PF_COLORSPACE_GRAYSCALE,
1339             previous->Xsize, previous->Ysize,
1340             l->omap_layers, NULL );
1341       }
1342 
1343       int iextra_min = 0;
1344       std::cout<<"Layer \""<<l->get_name()<<"\": inputs size: "<<l->inputs.size()<<std::endl;
1345       if( l->inputs.empty() || l->inputs[0].first.first < 0 ) {
1346         // input layer is not specified, we grab the default input
1347         std::pair< std::pair<int32_t,int32_t>,bool> input = get_default_input_layer(l);
1348         PF::Layer* ldef = get_layer(input.first.first);
1349         VipsImage* imdef = NULL;
1350         int imgid = input.first.second;
1351         PF::PipelineNode* ndef = pipeline->get_node(ldef);
1352         if( ndef ) {
1353           if( input.second == true ) {
1354             imdef = ndef->blended;
1355           } else {
1356             if( (imgid>=0) && (imgid<(int)ndef->images.size()) ) {
1357               imdef = ndef->images[imgid];
1358               //std::cout<<"  extra_node->images[imgid]="<<extra_node->images[imgid]<<std::endl;
1359             }
1360           }
1361         }
1362         in.push_back(imdef);
1363         //#ifndef NDEBUG
1364         if( ldef && imdef )
1365           std::cout<<"Layer \""<<l->get_name()<<"\": added \""<<ldef->get_name()<<"\"("<<imdef<<") as default input"<<std::endl;
1366         else
1367           std::cout<<"Layer \""<<l->get_name()<<"\": added "<<imdef<<" as default input"<<std::endl;
1368 //#endif
1369         iextra_min = 1;
1370       }
1371 
1372       // Now we loop on the vector of extra inputs, and we include the corresponding
1373       // images in the input vector
1374       for(uint32_t iextra = iextra_min; iextra < l->inputs.size(); iextra++) {
1375 #ifndef NDEBUG
1376         std::cout<<"Layer \""<<l->get_name()<<"\": adding extra input layer id="<<l->inputs[iextra].first.first
1377             <<" (blended="<<l->inputs[iextra].second<<")..."<<std::endl;
1378 #endif
1379         PF::Layer* lextra = get_layer( l->inputs[iextra].first.first );
1380         int imgid = l->inputs[iextra].first.second;
1381         // If the extra input layer is not found we have a problem, better to give up
1382         // with an error.
1383         //g_assert( lextra != NULL );
1384         if( !lextra ) {
1385           std::cout<<"Layer \""<<l->get_name()<<"\": extra input layer id="<<l->inputs[iextra].first.first
1386               <<" (blended="<<l->inputs[iextra].second<<") not found (NULL layer pointer)"<<std::endl;
1387           in.push_back( NULL );
1388           continue;
1389         }
1390         // If the layer is not visible (either bcause it is disabled,
1391         // or one of its parents is disabled) we ignore the associated image
1392         if( !(lextra->is_visible()) ) {
1393           std::cout<<"Layer \""<<l->get_name()<<"\": extra input layer id="<<l->inputs[iextra].first.first
1394               <<" (blended="<<l->inputs[iextra].second<<") not visible"<<std::endl;
1395           in.push_back( NULL );
1396           continue;
1397         }
1398         PF::PipelineNode* extra_node = pipeline->get_node( lextra->get_id() );
1399         //g_assert( extra_node != NULL );
1400         if( extra_node == NULL ) {
1401           std::cout<<"Layer \""<<l->get_name()<<"\": extra input layer id="<<l->inputs[iextra].first.first
1402               <<" (blended="<<l->inputs[iextra].second<<") node not found"<<std::endl;
1403           in.push_back( NULL );
1404           continue;
1405         }
1406         VipsImage* extra_img = NULL;
1407 #ifndef NDEBUG
1408         std::cout<<"  imgid="<<imgid<<"  extra_node->images.size()="<<extra_node->images.size()<<std::endl;
1409 #endif
1410         if( l->inputs[iextra].second == true ) {
1411           extra_img = extra_node->blended;
1412         } else {
1413           if( (imgid>=0) && (imgid<(int)extra_node->images.size()) ) {
1414             extra_img = extra_node->images[imgid];
1415             //std::cout<<"  extra_node->images[imgid]="<<extra_node->images[imgid]<<std::endl;
1416           }
1417         }
1418         // Similarly, if the extra input layer has no valid image associated to it
1419         // we have a problem and we gve up
1420         //g_assert( extra_img != NULL );
1421         if( extra_img == NULL ) {
1422           std::cout<<"Layer \""<<l->get_name()<<"\": extra input layer id="<<l->inputs[iextra].first.first
1423               <<" (blended="<<l->inputs[iextra].second<<") NULL image"<<std::endl;
1424           in.push_back( NULL );
1425           continue;
1426         }
1427         in.push_back( extra_img );
1428 
1429         // We inherit the image properties (size, colorspace, ...) from the last extra input
1430         pipelinepar->set_image_hints( extra_img );
1431         pipelineblender->set_image_hints( extra_img );
1432         if( par->is_map() ) {
1433           // If the layer is a mask, we force the output image colorspace to grayscale
1434           pipelinepar->grayscale_image( pipelinepar->get_xsize(), pipelinepar->get_ysize() );
1435           pipelineblender->grayscale_image( pipelinepar->get_xsize(), pipelinepar->get_ysize() );
1436         }
1437 #ifndef NDEBUG
1438         std::cout<<" ...added."<<std::endl;
1439 #endif
1440       }
1441 
1442       //if( par->get_config_ui() ) {
1443       //  par->get_config_ui()->update_properties();
1444       //}
1445 #ifndef NDEBUG
1446       std::cout<<"Building layer \""<<l->get_name()<<"\"..."<<std::endl;
1447 #endif
1448 
1449       // We import the parameters from the "master" operation associated to the layer,
1450       // and which is directly connected with the GUI controls
1451       //pipelinepar->import_settings( par );
1452 
1453       unsigned int level = pipeline->get_level();
1454 
1455       PF::PipelineNode* node_compat =
1456           image->get_compatible_node(l, pipeline, par->get_real_level(level));
1457 
1458       if( node_compat ) {
1459         newimgvec = node_compat->images;
1460         for(unsigned int ii = 0; ii < newimgvec.size(); ii++) {
1461           if( newimgvec[ii] ) PF_REF(newimgvec[ii], "rebuild_chain: newimgvec[ii] ref");
1462         }
1463         newimg = node_compat->image;
1464 //#ifndef NDEBUG
1465       std::cout<<"[rebuild_chain]: reusing existing node for layer \""<<l->get_name()<<"\"."<<std::endl;
1466 //#endif
1467       } else {
1468         newimgvec = pipelinepar->build_many_internal( in, 0, imap, omap, level );
1469         newimg = (newimgvec.empty()) ? NULL : newimgvec[0];
1470       }
1471       //cs = PF::convert_colorspace( pipelinepar->get_interpretation() );
1472       //std::cout<<"  par: "<<pipelinepar<<std::endl;
1473       //std::cout<<"  cs after build: "<<cs<<std::endl;
1474       //cs = PF::convert_colorspace( newimg->Type );
1475       //std::cout<<"  cs from newimg: "<<cs<<std::endl;
1476 #ifndef NDEBUG
1477       std::cout<<"... layer \""<<l->get_name()<<"\" finished"<<std::endl;
1478 #endif
1479 
1480       pipelinepar->clear_modified();
1481       pipeline->set_level( level );
1482 #ifndef NDEBUG
1483       if( newimg ) {
1484         std::cout<<"rebuild_chain(): Layer \""<<l->get_name()<<"\" level="<<level
1485             <<"  image size: "<<newimg->Xsize<<","<<newimg->Ysize<<std::endl
1486             <<"  inputs:";
1487         for(int i_in = 0; i_in < in.size(); i_in++)
1488           std::cout<<" 0x"<<in[i_in];
1489         std::cout<<std::endl<<"  output: 0x"<<newimg<<std::endl;
1490       }
1491       //#endif
1492       //#ifndef NDEBUG
1493       if( !newimg ) {
1494         std::cout<<"WARNING: NULL image from layer \""<<name<<"\""<<std::endl;
1495       } else {
1496         void *data;
1497         size_t data_length;
1498         if( vips_image_get_blob( newimg, VIPS_META_ICC_NAME,
1499             &data, &data_length ) ) {
1500           std::cout<<"WARNING: missing ICC profile from layer \""<<name<<"\""<<std::endl;
1501         } else {
1502           cmsHPROFILE profile_in = cmsOpenProfileFromMem( data, data_length );
1503           if( profile_in ) {
1504             char tstr[1024];
1505             cmsGetProfileInfoASCII(profile_in, cmsInfoDescription, "en", "US", tstr, 1024);
1506             std::cout<<"  Embedded profile found in layer \""<<name<<"\": "<<tstr<<std::endl;
1507           }
1508         }
1509       }
1510       std::cout<<"... done."<<std::endl;
1511 #endif
1512       //if( par->get_config_ui() ) par->get_config_ui()->update();
1513     } else {// if( l->sublayers.empty() )
1514       std::vector<VipsImage*> in;
1515 
1516       // we add the previous image to the list of inputs, even if it is NULL
1517       //in.push_back( previous );
1518 
1519       // Then we build the chain for the sub-layers, passing the previous image as the
1520       // initial input
1521       VipsImage* isub = NULL;
1522       if( previous )
1523         isub = rebuild_chain( pipeline, cs,
1524             previous->Xsize, previous->Ysize,
1525             l->sublayers, previous_layer );
1526       else
1527         isub = rebuild_chain( pipeline, cs,
1528             width, height,
1529             l->sublayers, NULL );
1530 
1531       // we add the output of the sub-layers chain to the list of inputs, even if it is NULL
1532       in.push_back( isub );
1533 
1534       // Then we build the chains for the intensity and opacity maps
1535 #ifndef NDEBUG
1536       std::cout<<"Layer \""<<l->get_name()<<"\""
1537           <<"  imap_layers.size()="<<l->imap_layers.size()
1538           <<"  omap_layers.size()="<<l->omap_layers.size()
1539           <<std::endl;
1540 #endif
1541       if( previous && !l->imap_layers.empty() && pipelinepar->get_mask_enabled()==true ) {
1542         imap = rebuild_chain( pipeline, PF_COLORSPACE_GRAYSCALE,
1543             previous->Xsize, previous->Ysize,
1544             l->imap_layers, NULL );
1545         //if( !imap ) return false;
1546         //std::list<PF::Layer*>::reverse_iterator map_i = l->imap_layers.rbegin();
1547         //if(map_i != l->imap_layers.rend())
1548         //imap = (*map_i)->get_processor()->get_par()->get_image();
1549       }
1550       if( previous && !l->omap_layers.empty() && pipelineblender->get_mask_enabled()==true ) {
1551         omap = rebuild_chain( pipeline, PF_COLORSPACE_GRAYSCALE,
1552             previous->Xsize, previous->Ysize,
1553             l->omap_layers, NULL );
1554         //if( !omap ) return false;
1555         //std::list<PF::Layer*>::reverse_iterator map_i = l->omap_layers.rbegin();
1556         //if(map_i != l->omap_layers.rend())
1557         //omap = (*map_i)->get_processor()->get_par()->get_image();
1558       }
1559 
1560       //if( par->get_config_ui() ) par->get_config_ui()->update_properties();
1561 #ifndef NDEBUG
1562       std::cout<<"Building layer \""<<l->get_name()<<"\"..."<<std::endl;
1563 #endif
1564       unsigned int level = pipeline->get_level();
1565       //pipelinepar->import_settings( par );
1566       newimgvec = pipelinepar->build_many_internal( in, 0, imap, omap, level );
1567       newimg = (newimgvec.empty()) ? NULL : newimgvec[0];
1568 #ifndef NDEBUG
1569       std::cout<<"... layer \""<<l->get_name()<<"\" finished"<<std::endl;
1570 #endif
1571 
1572       if( false && (newimg != NULL) && (newimgvec.size() == 1) && !image->is_loaded() && l->is_cached() &&
1573           (l->get_cache_buffer() != NULL) &&
1574           (l->get_cache_buffer()->is_completed() == false) ) {
1575         // The image is being loaded, and the current layer needs to be cached
1576         // In this case we cache the data immediately and we use the cached
1577         // image instead of the newly built one
1578         PF::CacheBuffer* buf = l->get_cache_buffer();
1579         buf->set_image( newimg );
1580 #ifndef NDEBUG
1581         std::cout<<"Writing cache buffer for layer "<<l->get_name()<<std::endl;
1582 #endif
1583         gint64 time1 = g_get_real_time();
1584         buf->write();
1585         gint64 time2 = g_get_real_time();
1586 #ifndef NDEBUG
1587         std::cout<<"Buffer saved in "<<(time2-time1)/1000000<<" seconds."<<std::endl;
1588 #endif
1589         PF_UNREF( newimg, "rebuild_chain(): newimg unref after cache buffer filling" );
1590 
1591         PF::PyramidLevel* pl = buf->get_pyramid().get_level( level );
1592         if( pl && pl->image ) {
1593           pipeline->set_level( level );
1594           newimg = pl->image;
1595           newimgvec[0] = pl->image;
1596         }
1597       }
1598 
1599       pipelinepar->clear_modified();
1600       pipeline->set_level( level );
1601 #ifndef NDEBUG
1602       if( newimg ) {
1603         std::cout<<"rebuild_chain(): Layer \""<<l->get_name()<<"\" level="<<level
1604             <<"  image size: "<<newimg->Xsize<<","<<newimg->Ysize<<std::endl
1605             <<"  inputs:";
1606         for(int i_in = 0; i_in < in.size(); i_in++)
1607           std::cout<<" 0x"<<in[i_in];
1608         std::cout<<std::endl<<"  output: 0x"<<newimg<<std::endl;
1609       }
1610 #endif
1611 #ifndef NDEBUG
1612       if( !newimg ) {
1613         std::cout<<"WARNING: NULL image from layer \""<<name<<"\""<<std::endl;
1614       } else {
1615         void *data;
1616         size_t data_length;
1617         if( vips_image_get_blob( newimg, VIPS_META_ICC_NAME,
1618             &data, &data_length ) ) {
1619           std::cout<<"WARNING: missing ICC profile from layer \""<<name<<"\""<<std::endl;
1620         } else {
1621           cmsHPROFILE profile_in = cmsOpenProfileFromMem( data, data_length );
1622           if( profile_in ) {
1623             char tstr[1024];
1624             cmsGetProfileInfoASCII(profile_in, cmsInfoDescription, "en", "US", tstr, 1024);
1625             std::cout<<"  Embedded profile found in layer \""<<name<<"\": "<<tstr<<std::endl;
1626           }
1627         }
1628       }
1629       std::cout<<"... done."<<std::endl;
1630 #endif
1631       //if( par->get_config_ui() ) par->get_config_ui()->update();
1632     }// if( l->sublayers.empty() )
1633 
1634     if( newimg ) {
1635       VipsImage* blendedimg;
1636 #ifndef NDEBUG
1637       std::cout<<"rebuild_chain(): Layer \""<<l->get_name()<<"\" newimgvec.size()="<<newimgvec.size()<<std::endl;
1638 #endif
1639       unsigned int level = pipeline->get_level();
1640       unsigned int level_real = par->get_real_level(level);
1641       pipeline->set_images( newimgvec, l->get_id(), level_real );
1642 
1643       bool needs_shrinking = (level_real != level) && par->do_shirnk_on_blend();
1644       if( needs_shrinking ) {
1645         float scale = 1;
1646         for(unsigned int l = 0; l < level; l++) scale /= 2;
1647         std::cout<<"rebuild_chain(): scaling layer \""<<l->get_name()<<"\" by "<<scale<<std::endl;
1648         VipsKernel kernel = VIPS_KERNEL_CUBIC;
1649         VipsImage* scaled;
1650         if( vips_resize(newimg, &scaled, scale, "kernel", kernel, NULL) ) {
1651           std::cout<<"rebuild_chain(): vips_resize() failed."<<std::endl;
1652           //PF_UNREF( interpolate, "ScalePar::build(): interpolate unref" );
1653         } else {
1654           newimg = scaled;
1655         }
1656 
1657         if( scaled && scale < 0.5 ) {
1658           VipsAccess acc = VIPS_ACCESS_RANDOM;
1659           int threaded = 1, persistent = 1;
1660           VipsImage* cached;
1661           if( !phf_tilecache(scaled, &cached,
1662               "access", acc, "threaded", threaded,
1663               "persistent", persistent, NULL) ) {
1664             PF_UNREF(scaled, "rebuild_chan: scaled unref");
1665             newimg = cached;
1666             std::cout<<"rebuild_chain(): added tilecache after scaling layer \""<<l->get_name()<<"\" by "<<scale<<std::endl;
1667           }
1668         }
1669       } else {
1670         PF_REF(newimg,"LayerManager::rebuild_chain(): newimg ref");
1671       }
1672 
1673       if( par->has_opacity() && blender && pipelineblender) {
1674         //pipelineblender->import_settings( blender );
1675 
1676         //std::cout<<"rebuild_chain(): blending images for layer \""<<l->get_name()<<"\""<<std::endl;
1677         std::vector<VipsImage*> in;
1678         // we add the previous image to the list of inputs, even if it is NULL
1679         in.push_back( previous );
1680         in.push_back( newimg );
1681         blendedimg = pipelineblender->build( in, 0, NULL, omap, level );
1682         PF_UNREF(newimg,"LayerManager::rebuild_chain(): newimg unref");
1683 #ifndef NDEBUG
1684         if(blendedimg)
1685           std::cout<<"rebuild_chain(): Layer \""<<l->get_name()<<"\" level="<<level
1686           <<"  blended size: "<<blendedimg->Xsize<<","<<blendedimg->Ysize<<std::endl;
1687 #endif
1688       } else {
1689         blendedimg = newimg;
1690         //PF_REF(blendedimg,"LayerManager::rebuild_chain(): blendedimg ref");
1691       }
1692 #ifndef NDEBUG
1693       std::cout<<"rebuild_chain(): Layer \""<<l->get_name()<<"\"  blended: "<<blendedimg<<std::endl;
1694 #endif
1695       pipeline->set_blended( blendedimg, l->get_id() );
1696       out = blendedimg;
1697       //previous = newimg;
1698       previous_layer = l;
1699     }
1700     if(pipelineblender) pipelineblender->clear_modified();
1701   }
1702   return out;
1703 }
1704 
1705 
rebuild_prepare()1706 bool PF::LayerManager::rebuild_prepare()
1707 {
1708 #ifndef NDEBUG
1709   std::cout<<"PF::LayerManager::rebuild_prepare(): layers.size()="<<layers.size()<<std::endl;
1710 #endif
1711   bool visible = true;
1712   update_visible( layers, visible );
1713 
1714   bool dirty = false;
1715   update_dirty( layers, dirty );
1716 
1717 #ifndef NDEBUG
1718   std::cout<<"PF::LayerManager::rebuild_prepare(): finished"<<std::endl;
1719 #endif
1720   if( !dirty ) {
1721     return false;
1722   }
1723   return true;
1724 }
1725 
1726 
rebuild(Pipeline * pipeline,colorspace_t cs,int width,int height,VipsRect * area)1727 bool PF::LayerManager::rebuild( Pipeline* pipeline, colorspace_t cs, int width, int height, VipsRect* area )
1728 {
1729   //Glib::Threads::Mutex::Lock lock( pipeline->get_mutex() );
1730 
1731 #ifndef NDEBUG
1732   std::cout<<"LayerManager::rebuild(): started."<<std::endl;
1733 #endif
1734   init_pipeline( pipeline, layers, NULL );
1735 #ifndef NDEBUG
1736   std::cout<<"LayerManager::rebuild(): after init_pipeline()"<<std::endl;
1737 #endif
1738 
1739   update_op_caching( pipeline );
1740 #ifndef NDEBUG
1741   std::cout<<"LayerManager::rebuild(): after update_op_caching()"<<std::endl;
1742 #endif
1743 
1744   if( pipeline && pipeline->get_output() ) {
1745     //vips_image_invalidate_all( pipeline->get_output() );
1746   }
1747   VipsImage* output = rebuild_chain( pipeline, cs, width, height, layers, NULL );
1748 #ifndef NDEBUG
1749   std::cout<<"LayerManager::rebuild(): chain rebuild finished."<<std::endl;
1750 #endif
1751   pipeline->set_output( output );
1752   pipeline->update( area );
1753   pipeline->clear_force_rebuild();
1754   //std::cout<<"LayerManager::rebuild(): pipeline updated."<<std::endl;
1755   return true;
1756 }
1757 
1758 
rebuild_finalize(bool ui_update)1759 bool PF::LayerManager::rebuild_finalize( bool ui_update )
1760 {
1761   reset_layers_dirty_flag( layers );
1762   //if( ui_update ) update_ui( layers );
1763   return true;
1764 }
1765 
1766 
1767 
1768 
rebuild_all(Pipeline * pipeline,colorspace_t cs,int width,int height)1769 bool PF::LayerManager::rebuild_all(Pipeline* pipeline, colorspace_t cs, int width, int height)
1770 {
1771   /*
1772   if( layers.empty() )
1773     return true;
1774   PF::Layer* l = *(layers.begin());
1775   l->set_dirty( true );
1776 
1777   if( !l->imap_layers.empty() ) {
1778     PF::Layer* ll = *(l->imap_layers.begin());
1779     ll->set_dirty( true );
1780   }
1781   if( !l->omap_layers.empty() ) {
1782     PF::Layer* ll = *(l->omap_layers.begin());
1783     ll->set_dirty( true );
1784   }
1785   if( !l->sublayers.empty() ) {
1786     PF::Layer* ll = *(l->sublayers.begin());
1787     ll->set_dirty( true );
1788   }
1789 
1790   bool dirty = false;
1791   update_dirty( layers, dirty );
1792 
1793   if( !dirty ) {
1794     return false;
1795   }
1796   */
1797 
1798   set_layers_dirty_flag( layers );
1799 
1800   VipsImage* output  = rebuild_chain( pipeline, cs, width, height, layers, NULL );
1801   pipeline->set_output( output );
1802 
1803   reset_layers_dirty_flag( layers );
1804 
1805 
1806 
1807   return true;
1808 }
1809 
1810 
1811 
save(std::ostream & ostr)1812 bool PF::LayerManager::save( std::ostream& ostr )
1813 {
1814   int level = 1;
1815   std::list<PF::Layer*>::iterator li;
1816   for(li = layers.begin(); li != layers.end(); ++li) {
1817     PF::Layer* l = *li;
1818     if( !l->save( ostr, level ) ) return false;
1819   }
1820   return true;
1821 }
1822