KiCad PCB EDA Suite
view.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2013-2017 CERN
5  * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
8  * @author Maciej Suminski <maciej.suminski@cern.ch>
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, you may find one here:
22  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23  * or you may search the http://www.gnu.org website for the version 2 license,
24  * or you may write to the Free Software Foundation, Inc.,
25  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26  */
27 
28 
29 #include <eda_item.h>
30 #include <layer_ids.h>
31 #include <trace_helpers.h>
32 
33 #include <view/view.h>
34 #include <view/view_group.h>
35 #include <view/view_item.h>
36 #include <view/view_rtree.h>
37 #include <view/view_overlay.h>
38 
39 #include <gal/definitions.h>
41 #include <painter.h>
42 
43 #ifdef KICAD_GAL_PROFILE
44 #include <profile.h>
45 #endif /* KICAD_GAL_PROFILE */
46 
47 namespace KIGFX {
48 
49 class VIEW;
50 
52 {
53 public:
55  m_view( nullptr ),
56  m_flags( KIGFX::VISIBLE ),
58  m_drawPriority( 0 ),
59  m_groups( nullptr ),
60  m_groupsSize( 0 ) {}
61 
63  {
64  deleteGroups();
65  }
66 
67  int GetFlags() const
68  {
69  return m_flags;
70  }
71 
72 private:
73  friend class VIEW;
74 
81  void getLayers( int* aLayers, int& aCount ) const
82  {
83  int* layersPtr = aLayers;
84 
85  for( int layer : m_layers )
86  *layersPtr++ = layer;
87 
88  aCount = m_layers.size();
89  }
90 
97  int getGroup( int aLayer ) const
98  {
99  for( int i = 0; i < m_groupsSize; ++i )
100  {
101  if( m_groups[i].first == aLayer )
102  return m_groups[i].second;
103  }
104 
105  return -1;
106  }
107 
114  void setGroup( int aLayer, int aGroup )
115  {
116  // Look if there is already an entry for the layer
117  for( int i = 0; i < m_groupsSize; ++i )
118  {
119  if( m_groups[i].first == aLayer )
120  {
121  m_groups[i].second = aGroup;
122  return;
123  }
124  }
125 
126  // If there was no entry for the given layer - create one
127  std::pair<int, int>* newGroups = new std::pair<int, int>[m_groupsSize + 1];
128 
129  if( m_groupsSize > 0 )
130  {
131  std::copy( m_groups, m_groups + m_groupsSize, newGroups );
132  delete[] m_groups;
133  }
134 
135  m_groups = newGroups;
136  newGroups[m_groupsSize++] = { aLayer, aGroup };
137  }
138 
139 
144  {
145  delete[] m_groups;
146  m_groups = nullptr;
147  m_groupsSize = 0;
148  }
149 
150 
156  inline bool storesGroups() const
157  {
158  return m_groupsSize > 0;
159  }
160 
161 
169  void reorderGroups( std::unordered_map<int, int> aReorderMap )
170  {
171  for( int i = 0; i < m_groupsSize; ++i )
172  {
173  int orig_layer = m_groups[i].first;
174  int new_layer = orig_layer;
175 
176  try
177  {
178  new_layer = aReorderMap.at( orig_layer );
179  }
180  catch( const std::out_of_range& )
181  {}
182 
183  m_groups[i].first = new_layer;
184  }
185  }
186 
193  void saveLayers( int* aLayers, int aCount )
194  {
195  m_layers.clear();
196 
197  for( int i = 0; i < aCount; ++i )
198  {
199  // this fires on some eagle board after EAGLE_PLUGIN::Load()
200  wxASSERT( unsigned( aLayers[i] ) <= unsigned( VIEW::VIEW_MAX_LAYERS ) );
201 
202  m_layers.push_back( aLayers[i] );
203  }
204  }
205 
209  int requiredUpdate() const
210  {
211  return m_requiredUpdate;
212  }
213 
218  {
220  }
221 
225  bool isRenderable() const
226  {
227  return m_flags == VISIBLE;
228  }
229 
231  int m_flags;
234 
235  std::pair<int, int>* m_groups;
236  int m_groupsSize;
238 
239  std::vector<int> m_layers;
240 };
241 
242 
244 {
245  VIEW_ITEM_DATA* data = aItem->viewPrivData();
246 
247  if( !data )
248  return;
249 
250  if( data->m_view )
251  data->m_view->VIEW::Remove( aItem );
252 
253  delete data;
254  aItem->ClearViewPrivData();
255 }
256 
257 
258 VIEW::VIEW( bool aIsDynamic ) :
259  m_enableOrderModifier( true ),
260  m_scale( 4.0 ),
261  m_minScale( 0.2 ), m_maxScale( 50000.0 ),
262  m_mirrorX( false ), m_mirrorY( false ),
263  m_painter( nullptr ),
264  m_gal( nullptr ),
265  m_dynamic( aIsDynamic ),
266  m_useDrawPriority( false ),
267  m_nextDrawPriority( 0 ),
268  m_reverseDrawOrder( false )
269 {
270  // Set m_boundary to define the max area size. The default area size
271  // is defined here as the max value of a int.
272  // this is a default value acceptable for Pcbnew and Gerbview, but too large for Eeschema.
273  // So in eeschema a call to SetBoundary() with a smaller value will be needed.
274  typedef std::numeric_limits<int> coord_limits;
275  double pos = coord_limits::lowest() / 2 + coord_limits::epsilon();
276  double size = coord_limits::max() - coord_limits::epsilon();
277  m_boundary.SetOrigin( pos, pos );
278  m_boundary.SetSize( size, size );
279 
280  m_allItems.reset( new std::vector<VIEW_ITEM*> );
281  m_allItems->reserve( 32768 );
282 
283  // Redraw everything at the beginning
284  MarkDirty();
285 
286  m_layers.reserve( VIEW_MAX_LAYERS );
287 
288  // View uses layers to display EDA_ITEMs (item may be displayed on several layers, for example
289  // pad may be shown on pad, pad hole and solder paste layers). There are usual copper layers
290  // (eg. F.Cu, B.Cu, internal and so on) and layers for displaying objects such as texts,
291  // silkscreen, pads, vias, etc.
292  for( int ii = 0; ii < VIEW_MAX_LAYERS; ++ii )
293  {
294  m_layers.emplace_back();
295  m_layers[ii].items = std::make_shared<VIEW_RTREE>();
296  m_layers[ii].id = ii;
297  m_layers[ii].renderingOrder = ii;
298  m_layers[ii].visible = true;
299  m_layers[ii].displayOnly = false;
300  m_layers[ii].diffLayer = false;
301  m_layers[ii].hasNegatives = false;
302  m_layers[ii].target = TARGET_CACHED;
303  }
304 
305  sortLayers();
306 
307  m_preview.reset( new KIGFX::VIEW_GROUP() );
308  Add( m_preview.get() );
309 }
310 
311 
313 {
314  Remove( m_preview.get() );
315 }
316 
317 
318 void VIEW::Add( VIEW_ITEM* aItem, int aDrawPriority )
319 {
320  int layers[VIEW_MAX_LAYERS], layers_count;
321 
322  if( aDrawPriority < 0 )
323  aDrawPriority = m_nextDrawPriority++;
324 
325  if( !aItem->m_viewPrivData )
326  aItem->m_viewPrivData = new VIEW_ITEM_DATA;
327 
328  aItem->m_viewPrivData->m_view = this;
329  aItem->m_viewPrivData->m_drawPriority = aDrawPriority;
330 
331  aItem->ViewGetLayers( layers, layers_count );
332  aItem->viewPrivData()->saveLayers( layers, layers_count );
333 
334  m_allItems->push_back( aItem );
335 
336  for( int i = 0; i < layers_count; ++i )
337  {
338  VIEW_LAYER& l = m_layers[layers[i]];
339  l.items->Insert( aItem );
340  MarkTargetDirty( l.target );
341  }
342 
343  SetVisible( aItem, true );
344  Update( aItem, KIGFX::INITIAL_ADD );
345 }
346 
347 
348 void VIEW::Remove( VIEW_ITEM* aItem )
349 {
350  if( !aItem )
351  return;
352 
353  auto viewData = aItem->viewPrivData();
354 
355  if( !viewData )
356  return;
357 
358  wxCHECK( viewData->m_view == this, /*void*/ );
359  auto item = std::find( m_allItems->begin(), m_allItems->end(), aItem );
360 
361  if( item != m_allItems->end() )
362  {
363  m_allItems->erase( item );
364  viewData->clearUpdateFlags();
365  }
366 
367  int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
368  viewData->getLayers( layers, layers_count );
369 
370  for( int i = 0; i < layers_count; ++i )
371  {
372  VIEW_LAYER& l = m_layers[layers[i]];
373  l.items->Remove( aItem );
374  MarkTargetDirty( l.target );
375 
376  // Clear the GAL cache
377  int prevGroup = viewData->getGroup( layers[i] );
378 
379  if( prevGroup >= 0 )
380  m_gal->DeleteGroup( prevGroup );
381  }
382 
383  viewData->deleteGroups();
384  viewData->m_view = nullptr;
385 }
386 
387 
388 void VIEW::SetRequired( int aLayerId, int aRequiredId, bool aRequired )
389 {
390  wxCHECK( (unsigned) aLayerId < m_layers.size(), /*void*/ );
391  wxCHECK( (unsigned) aRequiredId < m_layers.size(), /*void*/ );
392 
393  if( aRequired )
394  m_layers[aLayerId].requiredLayers.insert( aRequiredId );
395  else
396  m_layers[aLayerId].requiredLayers.erase( aRequired );
397 }
398 
399 
400 // stupid C++... python lambda would do this in one line
401 template <class CONTAINER>
403 {
404  typedef typename CONTAINER::value_type item_type;
405 
406  QUERY_VISITOR( CONTAINER& aCont, int aLayer ) :
407  m_cont( aCont ), m_layer( aLayer )
408  {
409  }
410 
411  bool operator()( VIEW_ITEM* aItem )
412  {
413  if( aItem->viewPrivData()->GetFlags() & VISIBLE )
414  m_cont.push_back( VIEW::LAYER_ITEM_PAIR( aItem, m_layer ) );
415 
416  return true;
417  }
418 
420  int m_layer;
421 };
422 
423 
424 int VIEW::Query( const BOX2I& aRect, std::vector<LAYER_ITEM_PAIR>& aResult ) const
425 {
426  if( m_orderedLayers.empty() )
427  return 0;
428 
429  std::vector<VIEW_LAYER*>::const_reverse_iterator i;
430 
431  // execute queries in reverse direction, so that items that are on the top of
432  // the rendering stack are returned first.
433  for( i = m_orderedLayers.rbegin(); i != m_orderedLayers.rend(); ++i )
434  {
435  // ignore layers that do not contain actual items (i.e. the selection box, menus, floats)
436  if( ( *i )->displayOnly || !( *i )->visible )
437  continue;
438 
439  QUERY_VISITOR<std::vector<LAYER_ITEM_PAIR> > visitor( aResult, ( *i )->id );
440  ( *i )->items->Query( aRect, visitor );
441  }
442 
443  return aResult.size();
444 }
445 
446 
447 VECTOR2D VIEW::ToWorld( const VECTOR2D& aCoord, bool aAbsolute ) const
448 {
449  const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
450 
451  if( aAbsolute )
452  return VECTOR2D( matrix * aCoord );
453  else
454  return VECTOR2D( matrix.GetScale().x * aCoord.x, matrix.GetScale().y * aCoord.y );
455 }
456 
457 
458 double VIEW::ToWorld( double aSize ) const
459 {
460  const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
461 
462  return fabs( matrix.GetScale().x * aSize );
463 }
464 
465 
466 VECTOR2D VIEW::ToScreen( const VECTOR2D& aCoord, bool aAbsolute ) const
467 {
468  const MATRIX3x3D& matrix = m_gal->GetWorldScreenMatrix();
469 
470  if( aAbsolute )
471  return VECTOR2D( matrix * aCoord );
472  else
473  return VECTOR2D( matrix.GetScale().x * aCoord.x, matrix.GetScale().y * aCoord.y );
474 }
475 
476 
477 double VIEW::ToScreen( double aSize ) const
478 {
479  const MATRIX3x3D& matrix = m_gal->GetWorldScreenMatrix();
480 
481  return matrix.GetScale().x * aSize;
482 }
483 
484 
485 void VIEW::CopySettings( const VIEW* aOtherView )
486 {
487  wxASSERT_MSG( false, wxT( "This is not implemented" ) );
488 }
489 
490 
491 void VIEW::SetGAL( GAL* aGal )
492 {
493  bool recacheGroups = ( m_gal != nullptr ); // recache groups only if GAL is reassigned
494  m_gal = aGal;
495 
496  // clear group numbers, so everything is going to be recached
497  if( recacheGroups )
498  clearGroupCache();
499 
500  // every target has to be refreshed
501  MarkDirty();
502 
503  // force the new GAL to display the current viewport.
504  SetCenter( m_center );
505  SetScale( m_scale );
507 }
508 
509 
511 {
512  BOX2D rect;
513  VECTOR2D screenSize = m_gal->GetScreenPixelSize();
514 
515  rect.SetOrigin( ToWorld( VECTOR2D( 0, 0 ) ) );
516  rect.SetEnd( ToWorld( screenSize ) );
517 
518  return rect.Normalize();
519 }
520 
521 
522 void VIEW::SetViewport( const BOX2D& aViewport )
523 {
524  VECTOR2D ssize = ToWorld( m_gal->GetScreenPixelSize(), false );
525 
526  wxCHECK( ssize.x > 0 && ssize.y > 0, /*void*/ );
527 
528  VECTOR2D centre = aViewport.Centre();
529  VECTOR2D vsize = aViewport.GetSize();
530  double zoom = 1.0 / std::max( fabs( vsize.x / ssize.x ), fabs( vsize.y / ssize.y ) );
531 
532  SetCenter( centre );
533  SetScale( GetScale() * zoom );
534 }
535 
536 
537 void VIEW::SetMirror( bool aMirrorX, bool aMirrorY )
538 {
539  wxASSERT_MSG( !aMirrorY, _( "Mirroring for Y axis is not supported yet" ) );
540 
541  m_mirrorX = aMirrorX;
542  m_mirrorY = aMirrorY;
543  m_gal->SetFlip( aMirrorX, aMirrorY );
544 
545  // Redraw everything
546  MarkDirty();
547 }
548 
549 
550 void VIEW::SetScale( double aScale, VECTOR2D aAnchor )
551 {
552  if( aAnchor == VECTOR2D( 0, 0 ) )
553  aAnchor = m_center;
554 
555  VECTOR2D a = ToScreen( aAnchor );
556 
557  if( aScale < m_minScale )
559  else if( aScale > m_maxScale )
561  else
562  m_scale = aScale;
563 
566 
567  VECTOR2D delta = ToWorld( a ) - aAnchor;
568 
569  SetCenter( m_center - delta );
570 
571  // Redraw everything after the viewport has changed
572  MarkDirty();
573 }
574 
575 
576 void VIEW::SetCenter( const VECTOR2D& aCenter )
577 {
578  m_center = aCenter;
579 
580  if( !m_boundary.Contains( aCenter ) )
581  {
582  if( m_center.x < m_boundary.GetLeft() )
584  else if( aCenter.x > m_boundary.GetRight() )
586 
587  if( m_center.y < m_boundary.GetTop() )
589  else if( m_center.y > m_boundary.GetBottom() )
591  }
592 
595 
596  // Redraw everything after the viewport has changed
597  MarkDirty();
598 }
599 
600 
601 void VIEW::SetCenter( const VECTOR2D& aCenter, const std::vector<BOX2D>& obscuringScreenRects )
602 {
603  if( obscuringScreenRects.empty() )
604  return SetCenter( aCenter );
605 
606  BOX2D screenRect( { 0, 0 }, m_gal->GetScreenPixelSize() );
607  SHAPE_POLY_SET unobscuredPoly( screenRect );
608  VECTOR2D unobscuredCenter = screenRect.Centre();
609 
610  for( const BOX2D& obscuringScreenRect : obscuringScreenRects )
611  {
612  SHAPE_POLY_SET obscuringPoly( obscuringScreenRect );
613  unobscuredPoly.BooleanSubtract( obscuringPoly, SHAPE_POLY_SET::PM_FAST );
614  }
615 
616  /*
617  * Perform a step-wise deflate to find the center of the largest unobscured area
618  */
619 
620  BOX2I bbox = unobscuredPoly.BBox();
621  int step = std::min( bbox.GetWidth(), bbox.GetHeight() ) / 10;
622 
623  while( !unobscuredPoly.IsEmpty() )
624  {
625  unobscuredCenter = (wxPoint) unobscuredPoly.BBox().Centre();
626  unobscuredPoly.Deflate( step, 4 );
627  }
628 
629  SetCenter( aCenter - ToWorld( unobscuredCenter - screenRect.Centre(), false ) );
630 }
631 
632 
633 void VIEW::SetLayerOrder( int aLayer, int aRenderingOrder )
634 {
635  m_layers[aLayer].renderingOrder = aRenderingOrder;
636 
637  sortLayers();
638 }
639 
640 
641 int VIEW::GetLayerOrder( int aLayer ) const
642 {
643  return m_layers.at( aLayer ).renderingOrder;
644 }
645 
646 
647 void VIEW::SortLayers( int aLayers[], int& aCount ) const
648 {
649  int maxLay, maxOrd, maxIdx;
650 
651  for( int i = 0; i < aCount; ++i )
652  {
653  maxLay = aLayers[i];
654  maxOrd = GetLayerOrder( maxLay );
655  maxIdx = i;
656 
657  // Look for the max element in the range (j..aCount)
658  for( int j = i; j < aCount; ++j )
659  {
660  if( maxOrd < GetLayerOrder( aLayers[j] ) )
661  {
662  maxLay = aLayers[j];
663  maxOrd = GetLayerOrder( maxLay );
664  maxIdx = j;
665  }
666  }
667 
668  // Swap elements
669  aLayers[maxIdx] = aLayers[i];
670  aLayers[i] = maxLay;
671  }
672 }
673 
674 
675 void VIEW::ReorderLayerData( std::unordered_map<int, int> aReorderMap )
676 {
677  std::vector<VIEW_LAYER> new_map;
678  new_map.reserve( m_layers.size() );
679 
680  for( int ii = 0; ii < VIEW_MAX_LAYERS; ++ii )
681  new_map.emplace_back();
682 
683  for( const VIEW_LAYER& layer : m_layers )
684  {
685  int orig_idx = layer.id;
686  int new_idx = orig_idx;
687 
688  if( aReorderMap.count( orig_idx ) )
689  new_idx = aReorderMap.at( orig_idx );
690 
691  new_map[new_idx] = layer;
692  new_map[new_idx].id = new_idx;
693  }
694 
695  m_layers = new_map;
696 
697  for( VIEW_ITEM* item : *m_allItems )
698  {
699  VIEW_ITEM_DATA* viewData = item->viewPrivData();
700 
701  if( !viewData )
702  continue;
703 
704  int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
705 
706  item->ViewGetLayers( layers, layers_count );
707  viewData->saveLayers( layers, layers_count );
708 
709  viewData->reorderGroups( aReorderMap );
710 
711  viewData->m_requiredUpdate |= COLOR;
712  }
713 
714  UpdateItems();
715 }
716 
717 
719 {
720  UPDATE_COLOR_VISITOR( int aLayer, PAINTER* aPainter, GAL* aGal ) :
721  layer( aLayer ),
722  painter( aPainter ),
723  gal( aGal )
724  {
725  }
726 
727  bool operator()( VIEW_ITEM* aItem )
728  {
729  // Obtain the color that should be used for coloring the item
730  const COLOR4D color = painter->GetSettings()->GetColor( aItem, layer );
731  int group = aItem->viewPrivData()->getGroup( layer );
732 
733  if( group >= 0 )
735 
736  return true;
737  }
738 
739  int layer;
742 };
743 
744 
745 void VIEW::UpdateLayerColor( int aLayer )
746 {
747  // There is no point in updating non-cached layers
748  if( !IsCached( aLayer ) )
749  return;
750 
751  BOX2I r;
752 
753  r.SetMaximum();
754 
755  if( m_gal->IsVisible() )
756  {
757  GAL_UPDATE_CONTEXT ctx( m_gal );
758 
759  UPDATE_COLOR_VISITOR visitor( aLayer, m_painter, m_gal );
760  m_layers[aLayer].items->Query( r, visitor );
761  MarkTargetDirty( m_layers[aLayer].target );
762  }
763 }
764 
765 
767 {
768  if( m_gal->IsVisible() )
769  {
770  GAL_UPDATE_CONTEXT ctx( m_gal );
771 
772  for( VIEW_ITEM* item : *m_allItems )
773  {
774  VIEW_ITEM_DATA* viewData = item->viewPrivData();
775 
776  if( !viewData )
777  continue;
778 
779  int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
780  viewData->getLayers( layers, layers_count );
781 
782  for( int i = 0; i < layers_count; ++i )
783  {
784  const COLOR4D color = m_painter->GetSettings()->GetColor( item, layers[i] );
785  int group = viewData->getGroup( layers[i] );
786 
787  if( group >= 0 )
789  }
790  }
791  }
792 
793  MarkDirty();
794 }
795 
796 
798 {
799  UPDATE_DEPTH_VISITOR( int aLayer, int aDepth, GAL* aGal ) :
800  layer( aLayer ),
801  depth( aDepth ),
802  gal( aGal )
803  {
804  }
805 
806  bool operator()( VIEW_ITEM* aItem )
807  {
808  int group = aItem->viewPrivData()->getGroup( layer );
809 
810  if( group >= 0 )
812 
813  return true;
814  }
815 
816  int layer, depth;
818 };
819 
820 
821 int VIEW::GetTopLayer() const
822 {
823  if( m_topLayers.size() == 0 )
824  return 0;
825 
826  return *m_topLayers.begin();
827 }
828 
829 
830 void VIEW::SetTopLayer( int aLayer, bool aEnabled )
831 {
832  if( aEnabled )
833  {
834  if( m_topLayers.count( aLayer ) == 1 )
835  return;
836 
837  m_topLayers.insert( aLayer );
838 
839  // Move the layer closer to front
841  m_layers[aLayer].renderingOrder += TOP_LAYER_MODIFIER;
842  }
843  else
844  {
845  if( m_topLayers.count( aLayer ) == 0 )
846  return;
847 
848  m_topLayers.erase( aLayer );
849 
850  // Restore the previous rendering order
852  m_layers[aLayer].renderingOrder -= TOP_LAYER_MODIFIER;
853  }
854 }
855 
856 
857 void VIEW::EnableTopLayer( bool aEnable )
858 {
859  if( aEnable == m_enableOrderModifier )
860  return;
861 
862  m_enableOrderModifier = aEnable;
863 
864  std::set<unsigned int>::iterator it;
865 
866  if( aEnable )
867  {
868  for( it = m_topLayers.begin(); it != m_topLayers.end(); ++it )
869  m_layers[*it].renderingOrder += TOP_LAYER_MODIFIER;
870  }
871  else
872  {
873  for( it = m_topLayers.begin(); it != m_topLayers.end(); ++it )
874  m_layers[*it].renderingOrder -= TOP_LAYER_MODIFIER;
875  }
876 
879 }
880 
881 
883 {
884  std::set<unsigned int>::iterator it;
885 
887  {
888  // Restore the previous rendering order for layers that were marked as top
889  for( it = m_topLayers.begin(); it != m_topLayers.end(); ++it )
890  m_layers[*it].renderingOrder -= TOP_LAYER_MODIFIER;
891  }
892 
893  m_topLayers.clear();
894 }
895 
896 
898 {
899  sortLayers();
900 
901  if( m_gal->IsVisible() )
902  {
903  GAL_UPDATE_CONTEXT ctx( m_gal );
904 
905  for( VIEW_ITEM* item : *m_allItems )
906  {
907  VIEW_ITEM_DATA* viewData = item->viewPrivData();
908 
909  if( !viewData )
910  continue;
911 
912  int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
913  viewData->getLayers( layers, layers_count );
914 
915  for( int i = 0; i < layers_count; ++i )
916  {
917  int group = viewData->getGroup( layers[i] );
918 
919  if( group >= 0 )
920  m_gal->ChangeGroupDepth( group, m_layers[layers[i]].renderingOrder );
921  }
922  }
923  }
924 
925  MarkDirty();
926 }
927 
928 
930 {
931  DRAW_ITEM_VISITOR( VIEW* aView, int aLayer, bool aUseDrawPriority, bool aReverseDrawOrder ) :
932  view( aView ),
933  layer( aLayer ),
934  useDrawPriority( aUseDrawPriority ),
935  reverseDrawOrder( aReverseDrawOrder )
936  {
937  }
938 
939  bool operator()( VIEW_ITEM* aItem )
940  {
941  wxCHECK( aItem->viewPrivData(), false );
942 
943  // Conditions that have to be fulfilled for an item to be drawn
944  bool drawCondition = aItem->viewPrivData()->isRenderable()
945  && aItem->ViewGetLOD( layer, view ) < view->m_scale;
946  if( !drawCondition )
947  return true;
948 
949  if( useDrawPriority )
950  drawItems.push_back( aItem );
951  else
952  view->draw( aItem, layer );
953 
954  return true;
955  }
956 
958  {
959  if( reverseDrawOrder )
960  {
961  std::sort( drawItems.begin(), drawItems.end(),
962  []( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool
963  {
964  return b->viewPrivData()->m_drawPriority < a->viewPrivData()->m_drawPriority;
965  });
966  }
967  else
968  {
969  std::sort( drawItems.begin(), drawItems.end(),
970  []( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool
971  {
972  return a->viewPrivData()->m_drawPriority < b->viewPrivData()->m_drawPriority;
973  });
974  }
975 
976  for( VIEW_ITEM* item : drawItems )
977  view->draw( item, layer );
978  }
979 
983  std::vector<VIEW_ITEM*> drawItems;
984 };
985 
986 
987 void VIEW::redrawRect( const BOX2I& aRect )
988 {
989  for( VIEW_LAYER* l : m_orderedLayers )
990  {
991  if( l->visible && IsTargetDirty( l->target ) && areRequiredLayersEnabled( l->id ) )
992  {
993  DRAW_ITEM_VISITOR drawFunc( this, l->id, m_useDrawPriority, m_reverseDrawOrder );
994 
995  m_gal->SetTarget( l->target );
996  m_gal->SetLayerDepth( l->renderingOrder );
997 
998  // Differential layer also work for the negatives, since both special layer types
999  // will composite on separate layers (at least in Cairo)
1000  if( l->diffLayer )
1001  m_gal->StartDiffLayer();
1002  else if( l->hasNegatives )
1004 
1005 
1006  l->items->Query( aRect, drawFunc );
1007 
1008  if( m_useDrawPriority )
1009  drawFunc.deferredDraw();
1010 
1011  if( l->diffLayer )
1012  m_gal->EndDiffLayer();
1013  else if( l->hasNegatives )
1015  }
1016  }
1017 }
1018 
1019 
1020 void VIEW::draw( VIEW_ITEM* aItem, int aLayer, bool aImmediate )
1021 {
1022  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1023 
1024  if( !viewData )
1025  return;
1026 
1027  if( IsCached( aLayer ) && !aImmediate )
1028  {
1029  // Draw using cached information or create one
1030  int group = viewData->getGroup( aLayer );
1031 
1032  if( group >= 0 )
1033  m_gal->DrawGroup( group );
1034  else
1035  Update( aItem );
1036  }
1037  else
1038  {
1039  // Immediate mode
1040  if( !m_painter->Draw( aItem, aLayer ) )
1041  aItem->ViewDraw( aLayer, this ); // Alternative drawing method
1042  }
1043 }
1044 
1045 
1046 void VIEW::draw( VIEW_ITEM* aItem, bool aImmediate )
1047 {
1048  int layers[VIEW_MAX_LAYERS], layers_count;
1049 
1050  aItem->ViewGetLayers( layers, layers_count );
1051 
1052  // Sorting is needed for drawing order dependent GALs (like Cairo)
1053  SortLayers( layers, layers_count );
1054 
1055  for( int i = 0; i < layers_count; ++i )
1056  {
1057  m_gal->SetLayerDepth( m_layers.at( layers[i] ).renderingOrder );
1058  draw( aItem, layers[i], aImmediate );
1059  }
1060 }
1061 
1062 
1063 void VIEW::draw( VIEW_GROUP* aGroup, bool aImmediate )
1064 {
1065  for( unsigned int i = 0; i < aGroup->GetSize(); i++)
1066  draw( aGroup->GetItem(i), aImmediate );
1067 }
1068 
1069 
1071 {
1072  RECACHE_ITEM_VISITOR( VIEW* aView, GAL* aGal, int aLayer ) :
1073  view( aView ),
1074  gal( aGal ),
1075  layer( aLayer )
1076  {
1077  }
1078 
1079  bool operator()( VIEW_ITEM* aItem )
1080  {
1081  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1082 
1083  if( !viewData )
1084  return false;
1085 
1086  // Remove previously cached group
1087  int group = viewData->getGroup( layer );
1088 
1089  if( group >= 0 )
1090  gal->DeleteGroup( group );
1091 
1092  viewData->setGroup( layer, -1 );
1093  view->Update( aItem );
1094 
1095  return true;
1096  }
1097 
1100  int layer;
1101 };
1102 
1103 
1105 {
1106  BOX2I r;
1107  r.SetMaximum();
1108  m_allItems->clear();
1109 
1110  for( VIEW_LAYER& layer : m_layers )
1111  layer.items->RemoveAll();
1112 
1113  m_nextDrawPriority = 0;
1114 
1115  m_gal->ClearCache();
1116 }
1117 
1118 
1120 {
1122  {
1123  // TARGET_CACHED and TARGET_NONCACHED have to be redrawn together, as they contain
1124  // layers that rely on each other (eg. netnames are noncached, but tracks - are cached)
1127 
1128  MarkDirty();
1129  }
1130 
1131  if( IsTargetDirty( TARGET_OVERLAY ) )
1132  {
1134  }
1135 }
1136 
1137 
1139 {
1140 #ifdef KICAD_GAL_PROFILE
1141  PROF_COUNTER totalRealTime;
1142 #endif /* KICAD_GAL_PROFILE */
1143 
1144  VECTOR2D screenSize = m_gal->GetScreenPixelSize();
1145  BOX2D rect( ToWorld( VECTOR2D( 0, 0 ) ),
1146  ToWorld( screenSize ) - ToWorld( VECTOR2D( 0, 0 ) ) );
1147 
1148  rect.Normalize();
1149  BOX2I recti( rect.GetPosition(), rect.GetSize() );
1150 
1151  // The view rtree uses integer positions. Large screens can overflow this size so in
1152  // this case, simply set the rectangle to the full rtree.
1153  if( rect.GetWidth() > std::numeric_limits<int>::max()
1154  || rect.GetHeight() > std::numeric_limits<int>::max() )
1155  {
1156  recti.SetMaximum();
1157  }
1158 
1159  redrawRect( recti );
1160 
1161  // All targets were redrawn, so nothing is dirty
1162  MarkClean();
1163 
1164 #ifdef KICAD_GAL_PROFILE
1165  totalRealTime.Stop();
1166  wxLogTrace( traceGalProfile, "VIEW::Redraw(): %.1f ms", totalRealTime.msecs() );
1167 #endif /* KICAD_GAL_PROFILE */
1168 }
1169 
1170 
1172 {
1173  return m_gal->GetScreenPixelSize();
1174 }
1175 
1176 
1178 {
1180  view( aView )
1181  {
1182  }
1183 
1184  bool operator()( VIEW_ITEM* aItem )
1185  {
1186  aItem->viewPrivData()->deleteGroups();
1187 
1188  return true;
1189  }
1190 
1192 };
1193 
1194 
1196 {
1197  BOX2I r;
1198 
1199  r.SetMaximum();
1200  CLEAR_LAYER_CACHE_VISITOR visitor( this );
1201 
1202  for( VIEW_LAYER& layer : m_layers )
1203  layer.items->Query( r, visitor );
1204 }
1205 
1206 
1207 void VIEW::invalidateItem( VIEW_ITEM* aItem, int aUpdateFlags )
1208 {
1209  if( aUpdateFlags & INITIAL_ADD )
1210  {
1211  // Don't update layers or bbox, since it was done in VIEW::Add()
1212  // Now that we have initialized, set flags to ALL for the code below
1213  aUpdateFlags = ALL;
1214  }
1215  else
1216  {
1217  // updateLayers updates geometry too, so we do not have to update both of them at the
1218  // same time
1219  if( aUpdateFlags & LAYERS )
1220  updateLayers( aItem );
1221  else if( aUpdateFlags & GEOMETRY )
1222  updateBbox( aItem );
1223  }
1224 
1225  int layers[VIEW_MAX_LAYERS], layers_count;
1226  aItem->ViewGetLayers( layers, layers_count );
1227 
1228  // Iterate through layers used by the item and recache it immediately
1229  for( int i = 0; i < layers_count; ++i )
1230  {
1231  int layerId = layers[i];
1232 
1233  if( IsCached( layerId ) )
1234  {
1235  if( aUpdateFlags & ( GEOMETRY | LAYERS | REPAINT ) )
1236  updateItemGeometry( aItem, layerId );
1237  else if( aUpdateFlags & COLOR )
1238  updateItemColor( aItem, layerId );
1239  }
1240 
1241  // Mark those layers as dirty, so the VIEW will be refreshed
1242  MarkTargetDirty( m_layers[layerId].target );
1243  }
1244 
1245  aItem->viewPrivData()->clearUpdateFlags();
1246 }
1247 
1248 
1250 {
1251  int n = 0;
1252 
1253  m_orderedLayers.resize( m_layers.size() );
1254 
1255  for( VIEW_LAYER& layer : m_layers )
1256  m_orderedLayers[n++] = &layer;
1257 
1258  sort( m_orderedLayers.begin(), m_orderedLayers.end(), compareRenderingOrder );
1259 
1260  MarkDirty();
1261 }
1262 
1263 
1264 void VIEW::updateItemColor( VIEW_ITEM* aItem, int aLayer )
1265 {
1266  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1267  wxCHECK( (unsigned) aLayer < m_layers.size(), /*void*/ );
1268  wxCHECK( IsCached( aLayer ), /*void*/ );
1269 
1270  if( !viewData )
1271  return;
1272 
1273  // Obtain the color that should be used for coloring the item on the specific layerId
1274  const COLOR4D color = m_painter->GetSettings()->GetColor( aItem, aLayer );
1275  int group = viewData->getGroup( aLayer );
1276 
1277  // Change the color, only if it has group assigned
1278  if( group >= 0 )
1280 }
1281 
1282 
1283 void VIEW::updateItemGeometry( VIEW_ITEM* aItem, int aLayer )
1284 {
1285  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1286  wxCHECK( (unsigned) aLayer < m_layers.size(), /*void*/ );
1287  wxCHECK( IsCached( aLayer ), /*void*/ );
1288 
1289  if( !viewData )
1290  return;
1291 
1292  VIEW_LAYER& l = m_layers.at( aLayer );
1293 
1294  m_gal->SetTarget( l.target );
1296 
1297  // Redraw the item from scratch
1298  int group = viewData->getGroup( aLayer );
1299 
1300  if( group >= 0 )
1301  m_gal->DeleteGroup( group );
1302 
1303  group = m_gal->BeginGroup();
1304  viewData->setGroup( aLayer, group );
1305 
1306  if( !m_painter->Draw( static_cast<EDA_ITEM*>( aItem ), aLayer ) )
1307  aItem->ViewDraw( aLayer, this ); // Alternative drawing method
1308 
1309  m_gal->EndGroup();
1310 }
1311 
1312 
1314 {
1315  int layers[VIEW_MAX_LAYERS], layers_count;
1316 
1317  aItem->ViewGetLayers( layers, layers_count );
1318 
1319  for( int i = 0; i < layers_count; ++i )
1320  {
1321  VIEW_LAYER& l = m_layers[layers[i]];
1322  l.items->Remove( aItem );
1323  l.items->Insert( aItem );
1324  MarkTargetDirty( l.target );
1325  }
1326 }
1327 
1328 
1330 {
1331  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1332  int layers[VIEW_MAX_LAYERS], layers_count;
1333 
1334  if( !viewData )
1335  return;
1336 
1337  // Remove the item from previous layer set
1338  viewData->getLayers( layers, layers_count );
1339 
1340  for( int i = 0; i < layers_count; ++i )
1341  {
1342  VIEW_LAYER& l = m_layers[layers[i]];
1343  l.items->Remove( aItem );
1344  MarkTargetDirty( l.target );
1345 
1346  if( IsCached( l.id ) )
1347  {
1348  // Redraw the item from scratch
1349  int prevGroup = viewData->getGroup( layers[i] );
1350 
1351  if( prevGroup >= 0 )
1352  {
1353  m_gal->DeleteGroup( prevGroup );
1354  viewData->setGroup( l.id, -1 );
1355  }
1356  }
1357  }
1358 
1359  // Add the item to new layer set
1360  aItem->ViewGetLayers( layers, layers_count );
1361  viewData->saveLayers( layers, layers_count );
1362 
1363  for( int i = 0; i < layers_count; i++ )
1364  {
1365  VIEW_LAYER& l = m_layers[layers[i]];
1366  l.items->Insert( aItem );
1367  MarkTargetDirty( l.target );
1368  }
1369 }
1370 
1371 
1372 bool VIEW::areRequiredLayersEnabled( int aLayerId ) const
1373 {
1374  wxCHECK( (unsigned) aLayerId < m_layers.size(), false );
1375 
1376  std::set<int>::const_iterator it, it_end;
1377 
1378  for( int layer : m_layers.at( aLayerId ).requiredLayers )
1379  {
1380  // That is enough if just one layer is not enabled
1381  if( !m_layers.at( layer ).visible || !areRequiredLayersEnabled( layer ) )
1382  return false;
1383  }
1384 
1385  return true;
1386 }
1387 
1388 
1390 {
1391  BOX2I r;
1392 
1393  r.SetMaximum();
1394 
1395  for( const VIEW_LAYER& l : m_layers )
1396  {
1397  if( IsCached( l.id ) )
1398  {
1399  RECACHE_ITEM_VISITOR visitor( this, m_gal, l.id );
1400  l.items->Query( r, visitor );
1401  }
1402  }
1403 }
1404 
1405 
1407 {
1408  if( m_gal->IsVisible() )
1409  {
1410  GAL_UPDATE_CONTEXT ctx( m_gal );
1411 
1412  for( VIEW_ITEM* item : *m_allItems )
1413  {
1414  if( item->viewPrivData() && item->viewPrivData()->m_requiredUpdate != NONE )
1415  {
1416  invalidateItem( item, item->viewPrivData()->m_requiredUpdate );
1417  item->viewPrivData()->m_requiredUpdate = NONE;
1418  }
1419  }
1420  }
1421 }
1422 
1423 
1424 void VIEW::UpdateAllItems( int aUpdateFlags )
1425 {
1426  for( VIEW_ITEM* item : *m_allItems )
1427  {
1428  if( item->viewPrivData() )
1429  item->viewPrivData()->m_requiredUpdate |= aUpdateFlags;
1430  }
1431 }
1432 
1433 
1434 void VIEW::UpdateAllItemsConditionally( int aUpdateFlags,
1435  std::function<bool( VIEW_ITEM* )> aCondition )
1436 {
1437  for( VIEW_ITEM* item : *m_allItems )
1438  {
1439  if( aCondition( item ) )
1440  {
1441  if( item->viewPrivData() )
1442  item->viewPrivData()->m_requiredUpdate |= aUpdateFlags;
1443  }
1444  }
1445 }
1446 
1447 
1448 std::unique_ptr<VIEW> VIEW::DataReference() const
1449 {
1450  std::unique_ptr<VIEW> ret = std::make_unique<VIEW>();
1451  ret->m_allItems = m_allItems;
1452  ret->m_layers = m_layers;
1453  ret->sortLayers();
1454  return ret;
1455 }
1456 
1457 
1458 void VIEW::SetVisible( VIEW_ITEM* aItem, bool aIsVisible )
1459 {
1460  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1461 
1462  if( !viewData )
1463  return;
1464 
1465  bool cur_visible = viewData->m_flags & VISIBLE;
1466 
1467  if( cur_visible != aIsVisible )
1468  {
1469  if( aIsVisible )
1470  viewData->m_flags |= VISIBLE;
1471  else
1472  viewData->m_flags &= ~VISIBLE;
1473 
1474  Update( aItem, APPEARANCE | COLOR );
1475  }
1476 }
1477 
1478 
1479 void VIEW::Hide( VIEW_ITEM* aItem, bool aHide )
1480 {
1481  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1482 
1483  if( !viewData )
1484  return;
1485 
1486  if( !( viewData->m_flags & VISIBLE ) )
1487  return;
1488 
1489  if( aHide )
1490  viewData->m_flags |= HIDDEN;
1491  else
1492  viewData->m_flags &= ~HIDDEN;
1493 
1494  Update( aItem, APPEARANCE );
1495 }
1496 
1497 
1498 bool VIEW::IsVisible( const VIEW_ITEM* aItem ) const
1499 {
1500  const VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1501 
1502  return viewData && ( viewData->m_flags & VISIBLE );
1503 }
1504 
1505 
1506 void VIEW::Update( const VIEW_ITEM* aItem ) const
1507 {
1508  Update( aItem, ALL );
1509 }
1510 
1511 
1512 void VIEW::Update( const VIEW_ITEM* aItem, int aUpdateFlags ) const
1513 {
1514  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1515 
1516  if( !viewData )
1517  return;
1518 
1519  assert( aUpdateFlags != NONE );
1520 
1521  viewData->m_requiredUpdate |= aUpdateFlags;
1522 }
1523 
1524 
1525 std::shared_ptr<VIEW_OVERLAY> VIEW::MakeOverlay()
1526 {
1527  std::shared_ptr<VIEW_OVERLAY> overlay( new VIEW_OVERLAY );
1528 
1529  Add( overlay.get() );
1530  return overlay;
1531 }
1532 
1533 
1535 {
1536  if( !m_preview )
1537  return;
1538 
1539  m_preview->Clear();
1540 
1541  for( EDA_ITEM *item : m_ownedItems )
1542  delete item;
1543 
1544  m_ownedItems.clear();
1545  Update( m_preview.get() );
1546 }
1547 
1548 
1550 {
1551  m_preview.reset( new KIGFX::VIEW_GROUP() );
1552  Add( m_preview.get() );
1553 }
1554 
1555 
1556 void VIEW::AddToPreview( EDA_ITEM* aItem, bool aTakeOwnership )
1557 {
1558  Hide( aItem, false );
1559  m_preview->Add( aItem );
1560 
1561  if( aTakeOwnership )
1562  m_ownedItems.push_back( aItem );
1563 
1564  SetVisible( m_preview.get(), true );
1565  Hide( m_preview.get(), false );
1566  Update( m_preview.get() );
1567 }
1568 
1569 
1570 void VIEW::ShowPreview( bool aShow )
1571 {
1572  SetVisible( m_preview.get(), aShow );
1573 }
1574 
1575 
1576 const int VIEW::TOP_LAYER_MODIFIER = -VIEW_MAX_LAYERS;
1577 
1578 } // namespace KIGFX
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition: profile.h:85
void Hide(VIEW_ITEM *aItem, bool aHide=true)
Temporarily hide the item in the view (e.g.
Definition: view.cpp:1479
virtual void DrawGroup(int aGroupNumber)
Draw the stored group.
Item is being added to the view.
Definition: view_item.h:51
Item is temporarily hidden (e.g.
Definition: view_item.h:61
int requiredUpdate() const
Return current update flag for an item.
Definition: view.cpp:209
void deleteGroups()
Remove all of the stored group ids.
Definition: view.cpp:143
BOX2D GetViewport() const
Return the current viewport visible area rectangle.
Definition: view.cpp:510
VIEW_ITEM_DATA * m_viewPrivData
Definition: view_item.h:151
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition: view.cpp:522
void updateLayers(VIEW_ITEM *aItem)
Determine rendering order of layers. Used in display order sorting function.
Definition: view.cpp:1329
void UpdateAllItemsConditionally(int aUpdateFlags, std::function< bool(VIEW_ITEM *)> aCondition)
Update items in the view according to the given flags and condition.
Definition: view.cpp:1434
CONTAINER & m_cont
Definition: view.cpp:419
void SetLayerOrder(int aLayer, int aRenderingOrder)
Set rendering order of a particular layer.
Definition: view.cpp:633
void SetRequired(int aLayerId, int aRequiredId, bool aRequired=true)
Mark the aRequiredId layer as required for the aLayerId layer.
Definition: view.cpp:388
void updateItemColor(VIEW_ITEM *aItem, int aLayer)
Update all information needed to draw an item.
Definition: view.cpp:1264
bool m_useDrawPriority
The next sequential drawing priority.
Definition: view.h:861
std::unique_ptr< KIGFX::VIEW_GROUP > m_preview
Definition: view.h:813
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:236
virtual void DeleteGroup(int aGroupNumber)
Delete the group from the memory.
virtual void SetTopLayer(int aLayer, bool aEnabled=true)
Set given layer to be displayed on the top or sets back the default order of layers.
Definition: view.cpp:830
std::shared_ptr< PNS_LOG_VIEWER_OVERLAY > overlay
Definition: playground.cpp:36
static const int TOP_LAYER_MODIFIER
Flag to respect draw priority when drawing items.
Definition: view.h:858
const MATRIX3x3D & GetScreenWorldMatrix() const
Get the screen <-> world transformation matrix.
void sortLayers()
Clear cached GAL group numbers (ONLY numbers stored in VIEW_ITEMs, not group objects used by GAL)
Definition: view.cpp:1249
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Converts a screen space point/vector to a point/vector in world space coordinates.
Definition: view.cpp:447
double msecs(bool aSinceLast=false)
Definition: profile.h:146
coord_type GetTop() const
Definition: box2.h:187
void AddToPreview(EDA_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1556
int color
Definition: DXF_plotter.cpp:57
void RecacheAllItems()
Rebuild GAL display lists.
Definition: view.cpp:1389
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition: view.cpp:1424
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:348
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:939
void SetFlip(bool xAxis, bool yAxis)
Sets flipping of the screen.
void InitPreview()
Definition: view.cpp:1549
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:1184
GAL * m_gal
Dynamic VIEW (eg.
Definition: view.h:848
bool areRequiredLayersEnabled(int aLayerId) const
Definition: view.cpp:1372
coord_type GetRight() const
Definition: box2.h:182
QUERY_VISITOR(CONTAINER &aCont, int aLayer)
Definition: view.cpp:406
std::set< unsigned int > m_topLayers
Center point of the VIEW (the point at which we are looking at).
Definition: view.h:831
void SetSize(const Vec &size)
Definition: box2.h:195
void clearUpdateFlags()
Mark an item as already updated, so it is not going to be redrawn.
Definition: view.cpp:217
const wxChar *const traceGalProfile
Flag to enable debug output of GAL performance profiling.
void UpdateAllLayersOrder()
Do everything that is needed to apply the rendering order of layers.
Definition: view.cpp:897
Visibility flag has changed.
Definition: view_item.h:47
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:1079
coord_type GetBottom() const
Definition: box2.h:183
void SetMirror(bool aMirrorX, bool aMirrorY)
Control the mirroring of the VIEW.
Definition: view.cpp:537
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:76
Color has changed.
Definition: view_item.h:48
All except INITIAL_ADD.
Definition: view_item.h:53
virtual void ComputeWorldScreenMatrix()
Compute the world <-> screen transformation matrix.
A small class to help profiling.
Definition: profile.h:45
virtual VIEW_ITEM * GetItem(unsigned int aIdx) const
Definition: view_group.cpp:81
virtual void SetLayerDepth(double aLayerDepth)
Set the depth of the layer (position on the z-axis)
std::shared_ptr< VIEW_OVERLAY > MakeOverlay()
Definition: view.cpp:1525
bool storesGroups() const
Return information if the item uses at least one group id (ie.
Definition: view.cpp:156
virtual void EnableTopLayer(bool aEnable)
Enable or disable display of the top layer.
Definition: view.cpp:857
void setGroup(int aLayer, int aGroup)
Set a group id for the item and the layer combination.
Definition: view.cpp:114
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
Definition: matrix3x3.h:265
VECTOR2D m_center
Definition: view.h:834
VIEW * m_view
Current dynamic view the item is assigned to.
Definition: view.cpp:230
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:411
static constexpr int VIEW_MAX_LAYERS
maximum number of layers that may be shown
Definition: view.h:711
virtual void EndGroup()
End the group.
Auxiliary rendering target (noncached)
Definition: definitions.h:49
std::shared_ptr< std::vector< VIEW_ITEM * > > m_allItems
The set of layers that are displayed on the top.
Definition: view.h:828
void SortLayers(int aLayers[], int &aCount) const
Change the order of given layer ids, so after sorting the order corresponds to layers rendering order...
Definition: view.cpp:647
int getGroup(int aLayer) const
Return number of the group id for the given layer, or -1 in case it was not cached before.
Definition: view.cpp:97
void ShowPreview(bool aShow=true)
Definition: view.cpp:1570
UPDATE_COLOR_VISITOR(int aLayer, PAINTER *aPainter, GAL *aGal)
Definition: view.cpp:720
double m_minScale
Definition: view.h:838
virtual void ChangeGroupColor(int aGroupNumber, const COLOR4D &aNewColor)
Change the color used to draw the group.
const VECTOR2I & GetScreenPixelSize() const
Return GAL canvas size in pixels.
virtual unsigned int GetSize() const
Return the number of stored items.
Definition: view_group.cpp:75
int layers[VIEW_MAX_LAYERS]
Definition: view.cpp:981
Contains all the knowledge about how to draw graphical object onto any particular output device.
Definition: painter.h:57
Item needs to be redrawn.
Definition: view_item.h:52
virtual void EndDiffLayer()
Ends rendering of a differential layer.
int m_drawPriority
Order to draw this item in a layer, lowest first.
Definition: view.cpp:233
void SetCenter(const VECTOR2D &aCenter)
Set the center point of the VIEW (i.e.
Definition: view.cpp:576
UPDATE_DEPTH_VISITOR(int aLayer, int aDepth, GAL *aGal)
Definition: view.cpp:799
VECTOR2< double > VECTOR2D
Definition: vector2d.h:622
virtual void Redraw()
Immediately redraws the whole view.
Definition: view.cpp:1138
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition: view.h:609
bool IsTargetDirty(int aTarget) const
Return true if any of layers belonging to the target or the target itself should be redrawn.
Definition: view.h:598
void Clear()
Remove all items from the view.
Definition: view.cpp:1104
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition: view.cpp:1498
Represent a set of closed polygons.
VIEW_ITEM_DATA * viewPrivData() const
Definition: view_item.h:138
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:727
virtual int GetTopLayer() const
Definition: view.cpp:821
coord_type GetWidth() const
Definition: box2.h:180
virtual int BeginGroup()
Begin a group.
BOX2< Vec > & Normalize()
Ensure that the height ant width are positive.
Definition: box2.h:112
bool Contains(const Vec &aPoint) const
Definition: box2.h:134
virtual void ClearTarget(RENDER_TARGET aTarget)
Clear the target for rendering.
void SetMaximum()
Definition: box2.h:57
virtual void ViewGetLayers(int aLayers[], int &aCount) const =0
Return the all the layers within the VIEW the object is painted on.
bool m_mirrorX
Definition: view.h:841
void invalidateItem(VIEW_ITEM *aItem, int aUpdateFlags)
Manage dirty flags & redraw queuing when updating an item.
Definition: view.cpp:1207
void ClearPreview()
Definition: view.cpp:1534
const VECTOR2I & GetScreenPixelSize() const
Return the size of the our rendering area in pixels.
Definition: view.cpp:1171
void reorderGroups(std::unordered_map< int, int > aReorderMap)
Reorder the stored groups (to facilitate reordering of layers).
Definition: view.cpp:169
Extend VIEW_ITEM by possibility of grouping items into a single object.
Definition: view_group.h:46
int id
Layer ID.
Definition: view.h:722
Items that may change while the view stays the same (noncached)
Definition: definitions.h:50
#define _(s)
wxLogTrace helper definitions.
void ReorderLayerData(std::unordered_map< int, int > aReorderMap)
Remap the data between layer ids without invalidating that data.
Definition: view.cpp:675
void UpdateItems()
Iterate through the list of items that asked for updating and updates them.
Definition: view.cpp:1406
void updateBbox(VIEW_ITEM *aItem)
Update set of layers that an item occupies.
Definition: view.cpp:1313
virtual void StartNegativesLayer()
Begins rendering in a new layer that will be copied to the main layer in EndNegativesLayer().
PAINTER * m_painter
Interface to #PAINTER that is used to draw items.
Definition: view.h:845
bool m_reverseDrawOrder
Definition: view.h:867
Item is visible (in general)
Definition: view_item.h:60
E_SERIE r
Definition: eserie.cpp:41
int m_nextDrawPriority
Flag to reverse the draw order when using draw priority.
Definition: view.h:864
VECTOR2D ToScreen(const VECTOR2D &aCoord, bool aAbsolute=true) const
Convert a world space point/vector to a point/vector in screen space coordinates.
Definition: view.cpp:466
void saveLayers(int *aLayers, int aCount)
Save layers used by the item.
Definition: view.cpp:193
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:806
std::vector< VIEW_LAYER > m_layers
Sorted list of pointers to members of m_layers.
Definition: view.h:822
void ClearTopLayers()
Remove all layers from the on-the-top set (they are no longer displayed over the rest of layers).
Definition: view.cpp:882
virtual bool Draw(const VIEW_ITEM *aItem, int aLayer)=0
Takes an instance of VIEW_ITEM and passes it to a function that knows how to draw the item.
void SetEnd(coord_type x, coord_type y)
Definition: box2.h:207
const Vec & GetPosition() const
Definition: box2.h:177
virtual void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 })
Set the scaling factor, zooming around a given anchor point.
Definition: view.cpp:550
virtual void StartDiffLayer()
Begins rendering of a differential layer.
void clearGroupCache()
Definition: view.cpp:1195
double m_maxScale
Definition: view.h:839
void UpdateLayerColor(int aLayer)
Apply the new coloring scheme held by RENDER_SETTINGS in case that it has changed.
Definition: view.cpp:745
std::unique_ptr< VIEW > DataReference() const
Return a new VIEW object that shares the same set of VIEW_ITEMs and LAYERs.
Definition: view.cpp:1448
std::pair< int, int > * m_groups
layer_number:group_id pairs for each layer the item occupies.
Definition: view.cpp:235
No updates are required.
Definition: view_item.h:46
virtual COLOR4D GetColor(const VIEW_ITEM *aItem, int aLayer) const =0
Returns the color that should be used to draw the specific VIEW_ITEM on the specific layer using curr...
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
CONTAINER::value_type item_type
Definition: view.cpp:404
void redrawRect(const BOX2I &aRect)
Definition: view.cpp:987
bool isRenderable() const
Return if the item should be drawn or not.
Definition: view.cpp:225
std::vector< EDA_ITEM * > m_ownedItems
Whether to use rendering order modifier or not.
Definition: view.h:816
void updateItemGeometry(VIEW_ITEM *aItem, int aLayer)
Update bounding box of an item.
Definition: view.cpp:1283
Main rendering target (cached)
Definition: definitions.h:48
Vec Centre() const
Definition: box2.h:63
bool m_enableOrderModifier
The set of possible displayed layers and its properties.
Definition: view.h:819
static void OnDestroy(VIEW_ITEM *aItem)
Nasty hack, invoked by the destructor of VIEW_ITEM to auto-remove the item from the owning VIEW if th...
Definition: view.cpp:243
BOX2D m_boundary
Definition: view.h:837
std::vector< VIEW_LAYER * > m_orderedLayers
Flat list of all items.
Definition: view.h:825
void MarkClean()
Force redraw of view on the next rendering.
Definition: view.h:642
std::pair< VIEW_ITEM *, int > LAYER_ITEM_PAIR
Definition: view.h:73
int GetLayerOrder(int aLayer) const
Return rendering order of a particular layer.
Definition: view.cpp:641
void draw(VIEW_ITEM *aItem, int aLayer, bool aImmediate=false)
Draw an item, but on a specified layers.
Definition: view.cpp:1020
bool IsCached(int aLayer) const
Return true if the layer is cached.
Definition: view.h:616
void SetOrigin(const Vec &pos)
Definition: box2.h:193
virtual bool IsVisible() const
Return true if the GAL canvas is visible on the screen.
void SetZoomFactor(double aZoomFactor)
Set the zoom factor of the scene.
virtual void ChangeGroupDepth(int aGroupNumber, int aDepth)
Change the depth (Z-axis position) of the group.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
bool m_mirrorY
PAINTER contains information how do draw items.
Definition: view.h:842
void ClearTargets()
Clear targets that are marked as dirty.
Definition: view.cpp:1119
coord_type GetHeight() const
Definition: box2.h:181
int m_flags
Visibility flags.
Definition: view.cpp:231
void ClearViewPrivData()
Definition: view_item.h:143
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1458
virtual void EndNegativesLayer()
Ends rendering of a negatives layer and draws it to the main layer.
void CopySettings(const VIEW *aOtherView)
Copy layers and visibility settings from another view.
Definition: view.cpp:485
double m_scale
Definition: view.h:836
Layers have changed.
Definition: view_item.h:50
constexpr int delta
int renderingOrder
Rendering order of this layer.
Definition: view.h:721
void SetLookAtPoint(const VECTOR2D &aPoint)
Set the Point in world space to look at.
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:318
const Vec & GetSize() const
Definition: box2.h:172
virtual int Query(const BOX2I &aRect, std::vector< LAYER_ITEM_PAIR > &aResult) const
Find all visible items that touch or are within the rectangle aRect.
Definition: view.cpp:424
coord_type GetLeft() const
Definition: box2.h:186
virtual ~VIEW()
Definition: view.cpp:312
VIEW(bool aIsDynamic=true)
Definition: view.cpp:258
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
DRAW_ITEM_VISITOR(VIEW *aView, int aLayer, bool aUseDrawPriority, bool aReverseDrawOrder)
Definition: view.cpp:931
int GetFlags() const
Definition: view.cpp:67
const MATRIX3x3D & GetWorldScreenMatrix() const
Get the world <-> screen transformation matrix.
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition: view.cpp:766
double GetScale() const
Definition: view.h:264
std::vector< int > m_layers
Definition: view.cpp:239
void SetGAL(GAL *aGal)
Assign a rendering device for the VIEW.
Definition: view.cpp:491
int m_requiredUpdate
Flag required for updating.
Definition: view.cpp:232
static bool compareRenderingOrder(VIEW_LAYER *aI, VIEW_LAYER *aJ)
Check if every layer required by the aLayerId layer is enabled.
Definition: view.h:800
virtual void ClearCache()
Delete all data created during caching of graphic items.
virtual void SetTarget(RENDER_TARGET aTarget)
Set the target for rendering.
void MarkDirty()
Force redraw of view on the next rendering.
Definition: view.h:633
virtual double ViewGetLOD(int aLayer, VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition: view_item.h:132
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1512
std::vector< VIEW_ITEM * > drawItems
Definition: view.cpp:983
void getLayers(int *aLayers, int &aCount) const
Return layer numbers used by the item.
Definition: view.cpp:81
Abstract interface for drawing on a 2D-surface.
Position or shape has changed.
Definition: view_item.h:49
RECACHE_ITEM_VISITOR(VIEW *aView, GAL *aGal, int aLayer)
Definition: view.cpp:1072
virtual void ViewDraw(int aLayer, VIEW *aView) const
Draw the parts of the object belonging to layer aLayer.
Definition: view_item.h:106
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103
RENDER_TARGET target
Where the layer should be rendered.
Definition: view.h:723
std::shared_ptr< VIEW_RTREE > items
R-tree indexing all items on this layer.
Definition: view.h:720