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>
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  GroupPair* newGroups = new GroupPair[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++] = GroupPair( 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  m_groups[i].first = new_layer;
183  }
184  }
185 
192  void saveLayers( int* aLayers, int aCount )
193  {
194  m_layers.clear();
195 
196  for( int i = 0; i < aCount; ++i )
197  {
198  // this fires on some eagle board after EAGLE_PLUGIN::Load()
199  wxASSERT( unsigned( aLayers[i] ) <= unsigned( VIEW::VIEW_MAX_LAYERS ) );
200 
201  m_layers.push_back( aLayers[i] );
202  }
203  }
204 
208  int requiredUpdate() const
209  {
210  return m_requiredUpdate;
211  }
212 
217  {
219  }
220 
224  bool isRenderable() const
225  {
226  return m_flags == VISIBLE;
227  }
228 
229 
231  int m_flags;
234 
236  typedef std::pair<int, int> GroupPair;
237 
242 
244  std::vector<int> m_layers;
245 };
246 
247 
249 {
250  VIEW_ITEM_DATA* data = aItem->viewPrivData();
251 
252  if( !data )
253  return;
254 
255  if( data->m_view )
256  data->m_view->VIEW::Remove( aItem );
257 
258  delete data;
259  aItem->ClearViewPrivData();
260 }
261 
262 
263 VIEW::VIEW( bool aIsDynamic ) :
264  m_enableOrderModifier( true ),
265  m_scale( 4.0 ),
266  m_minScale( 0.2 ), m_maxScale( 50000.0 ),
267  m_mirrorX( false ), m_mirrorY( false ),
268  m_painter( nullptr ),
269  m_gal( nullptr ),
270  m_dynamic( aIsDynamic ),
271  m_useDrawPriority( false ),
272  m_nextDrawPriority( 0 ),
273  m_reverseDrawOrder( false )
274 {
275  // Set m_boundary to define the max area size. The default area size
276  // is defined here as the max value of a int.
277  // this is a default value acceptable for Pcbnew and Gerbview, but too large for Eeschema.
278  // So in eeschema a call to SetBoundary() with a smaller value will be needed.
279  typedef std::numeric_limits<int> coord_limits;
280  double pos = coord_limits::lowest() / 2 + coord_limits::epsilon();
281  double size = coord_limits::max() - coord_limits::epsilon();
282  m_boundary.SetOrigin( pos, pos );
283  m_boundary.SetSize( size, size );
284 
285  m_allItems.reset( new std::vector<VIEW_ITEM*> );
286  m_allItems->reserve( 32768 );
287 
288  // Redraw everything at the beginning
289  MarkDirty();
290 
291  m_layers.reserve( VIEW_MAX_LAYERS );
292 
293  // View uses layers to display EDA_ITEMs (item may be displayed on several layers, for example
294  // pad may be shown on pad, pad hole and solder paste layers). There are usual copper layers
295  // (eg. F.Cu, B.Cu, internal and so on) and layers for displaying objects such as texts,
296  // silkscreen, pads, vias, etc.
297  for( int ii = 0; ii < VIEW_MAX_LAYERS; ++ii )
298  {
299  m_layers.emplace_back();
300  m_layers[ii].items = std::make_shared<VIEW_RTREE>();
301  m_layers[ii].id = ii;
302  m_layers[ii].renderingOrder = ii;
303  m_layers[ii].visible = true;
304  m_layers[ii].displayOnly = false;
305  m_layers[ii].target = TARGET_CACHED;
306  }
307 
308  sortLayers();
309 
310  m_preview.reset( new KIGFX::VIEW_GROUP() );
311  Add( m_preview.get() );
312 }
313 
314 
316 {
317  Remove( m_preview.get() );
318 }
319 
320 
321 void VIEW::Add( VIEW_ITEM* aItem, int aDrawPriority )
322 {
323  int layers[VIEW_MAX_LAYERS], layers_count;
324 
325  if( aDrawPriority < 0 )
326  aDrawPriority = m_nextDrawPriority++;
327 
328  if( !aItem->m_viewPrivData )
329  aItem->m_viewPrivData = new VIEW_ITEM_DATA;
330 
331  aItem->m_viewPrivData->m_view = this;
332  aItem->m_viewPrivData->m_drawPriority = aDrawPriority;
333 
334  aItem->ViewGetLayers( layers, layers_count );
335  aItem->viewPrivData()->saveLayers( layers, layers_count );
336 
337  m_allItems->push_back( aItem );
338 
339  for( int i = 0; i < layers_count; ++i )
340  {
341  VIEW_LAYER& l = m_layers[layers[i]];
342  l.items->Insert( aItem );
343  MarkTargetDirty( l.target );
344  }
345 
346  SetVisible( aItem, true );
347  Update( aItem, KIGFX::INITIAL_ADD );
348 }
349 
350 
351 void VIEW::Remove( VIEW_ITEM* aItem )
352 {
353  if( !aItem )
354  return;
355 
356  auto viewData = aItem->viewPrivData();
357 
358  if( !viewData )
359  return;
360 
361  wxCHECK( viewData->m_view == this, /*void*/ );
362  auto item = std::find( m_allItems->begin(), m_allItems->end(), aItem );
363 
364  if( item != m_allItems->end() )
365  {
366  m_allItems->erase( item );
367  viewData->clearUpdateFlags();
368  }
369 
370  int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
371  viewData->getLayers( layers, layers_count );
372 
373  for( int i = 0; i < layers_count; ++i )
374  {
375  VIEW_LAYER& l = m_layers[layers[i]];
376  l.items->Remove( aItem );
377  MarkTargetDirty( l.target );
378 
379  // Clear the GAL cache
380  int prevGroup = viewData->getGroup( layers[i] );
381 
382  if( prevGroup >= 0 )
383  m_gal->DeleteGroup( prevGroup );
384  }
385 
386  viewData->deleteGroups();
387  viewData->m_view = nullptr;
388 }
389 
390 
391 void VIEW::SetRequired( int aLayerId, int aRequiredId, bool aRequired )
392 {
393  wxCHECK( (unsigned) aLayerId < m_layers.size(), /*void*/ );
394  wxCHECK( (unsigned) aRequiredId < m_layers.size(), /*void*/ );
395 
396  if( aRequired )
397  m_layers[aLayerId].requiredLayers.insert( aRequiredId );
398  else
399  m_layers[aLayerId].requiredLayers.erase( aRequired );
400 }
401 
402 
403 // stupid C++... python lambda would do this in one line
404 template <class CONTAINER>
406 {
407  typedef typename CONTAINER::value_type item_type;
408 
409  QUERY_VISITOR( CONTAINER& aCont, int aLayer ) :
410  m_cont( aCont ), m_layer( aLayer )
411  {
412  }
413 
414  bool operator()( VIEW_ITEM* aItem )
415  {
416  if( aItem->viewPrivData()->getFlags() & VISIBLE )
417  m_cont.push_back( VIEW::LAYER_ITEM_PAIR( aItem, m_layer ) );
418 
419  return true;
420  }
421 
423  int m_layer;
424 };
425 
426 
427 int VIEW::Query( const BOX2I& aRect, std::vector<LAYER_ITEM_PAIR>& aResult ) const
428 {
429  if( m_orderedLayers.empty() )
430  return 0;
431 
432  std::vector<VIEW_LAYER*>::const_reverse_iterator i;
433 
434  // execute queries in reverse direction, so that items that are on the top of
435  // the rendering stack are returned first.
436  for( i = m_orderedLayers.rbegin(); i != m_orderedLayers.rend(); ++i )
437  {
438  // ignore layers that do not contain actual items (i.e. the selection box, menus, floats)
439  if( ( *i )->displayOnly || !( *i )->visible )
440  continue;
441 
442  QUERY_VISITOR<std::vector<LAYER_ITEM_PAIR> > visitor( aResult, ( *i )->id );
443  ( *i )->items->Query( aRect, visitor );
444  }
445 
446  return aResult.size();
447 }
448 
449 
450 VECTOR2D VIEW::ToWorld( const VECTOR2D& aCoord, bool aAbsolute ) const
451 {
452  const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
453 
454  if( aAbsolute )
455  return VECTOR2D( matrix * aCoord );
456  else
457  return VECTOR2D( matrix.GetScale().x * aCoord.x, matrix.GetScale().y * aCoord.y );
458 }
459 
460 
461 double VIEW::ToWorld( double aSize ) const
462 {
463  const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
464 
465  return fabs( matrix.GetScale().x * aSize );
466 }
467 
468 
469 VECTOR2D VIEW::ToScreen( const VECTOR2D& aCoord, bool aAbsolute ) const
470 {
471  const MATRIX3x3D& matrix = m_gal->GetWorldScreenMatrix();
472 
473  if( aAbsolute )
474  return VECTOR2D( matrix * aCoord );
475  else
476  return VECTOR2D( matrix.GetScale().x * aCoord.x, matrix.GetScale().y * aCoord.y );
477 }
478 
479 
480 double VIEW::ToScreen( double aSize ) const
481 {
482  const MATRIX3x3D& matrix = m_gal->GetWorldScreenMatrix();
483 
484  return matrix.GetScale().x * aSize;
485 }
486 
487 
488 void VIEW::CopySettings( const VIEW* aOtherView )
489 {
490  wxASSERT_MSG( false, wxT( "This is not implemented" ) );
491 }
492 
493 
494 void VIEW::SetGAL( GAL* aGal )
495 {
496  bool recacheGroups = ( m_gal != nullptr ); // recache groups only if GAL is reassigned
497  m_gal = aGal;
498 
499  // clear group numbers, so everything is going to be recached
500  if( recacheGroups )
501  clearGroupCache();
502 
503  // every target has to be refreshed
504  MarkDirty();
505 
506  // force the new GAL to display the current viewport.
507  SetCenter( m_center );
508  SetScale( m_scale );
510 }
511 
512 
514 {
515  BOX2D rect;
516  VECTOR2D screenSize = m_gal->GetScreenPixelSize();
517 
518  rect.SetOrigin( ToWorld( VECTOR2D( 0, 0 ) ) );
519  rect.SetEnd( ToWorld( screenSize ) );
520 
521  return rect.Normalize();
522 }
523 
524 
525 void VIEW::SetViewport( const BOX2D& aViewport )
526 {
527  VECTOR2D ssize = ToWorld( m_gal->GetScreenPixelSize(), false );
528 
529  wxCHECK( ssize.x > 0 && ssize.y > 0, /*void*/ );
530 
531  VECTOR2D centre = aViewport.Centre();
532  VECTOR2D vsize = aViewport.GetSize();
533  double zoom = 1.0 / std::max( fabs( vsize.x / ssize.x ), fabs( vsize.y / ssize.y ) );
534 
535  SetCenter( centre );
536  SetScale( GetScale() * zoom );
537 }
538 
539 
540 void VIEW::SetMirror( bool aMirrorX, bool aMirrorY )
541 {
542  wxASSERT_MSG( !aMirrorY, _( "Mirroring for Y axis is not supported yet" ) );
543 
544  m_mirrorX = aMirrorX;
545  m_mirrorY = aMirrorY;
546  m_gal->SetFlip( aMirrorX, aMirrorY );
547 
548  // Redraw everything
549  MarkDirty();
550 }
551 
552 
553 void VIEW::SetScale( double aScale, VECTOR2D aAnchor )
554 {
555  if( aAnchor == VECTOR2D( 0, 0 ) )
556  aAnchor = m_center;
557 
558  VECTOR2D a = ToScreen( aAnchor );
559 
560  if( aScale < m_minScale )
562  else if( aScale > m_maxScale )
564  else
565  m_scale = aScale;
566 
569 
570  VECTOR2D delta = ToWorld( a ) - aAnchor;
571 
572  SetCenter( m_center - delta );
573 
574  // Redraw everything after the viewport has changed
575  MarkDirty();
576 }
577 
578 
579 void VIEW::SetCenter( const VECTOR2D& aCenter )
580 {
581  m_center = aCenter;
582 
583  if( !m_boundary.Contains( aCenter ) )
584  {
585  if( m_center.x < m_boundary.GetLeft() )
587  else if( aCenter.x > m_boundary.GetRight() )
589 
590  if( m_center.y < m_boundary.GetTop() )
592  else if( m_center.y > m_boundary.GetBottom() )
594  }
595 
598 
599  // Redraw everything after the viewport has changed
600  MarkDirty();
601 }
602 
603 
604 void VIEW::SetCenter( const VECTOR2D& aCenter, const BOX2D& occultingScreenRect )
605 {
606  VECTOR2D center( aCenter );
607  BOX2D screenRect( VECTOR2D( 0, 0 ), m_gal->GetScreenPixelSize() );
608 
609  if( !screenRect.Intersects( occultingScreenRect ) )
610  {
611  SetCenter( aCenter );
612  return;
613  }
614 
615  BOX2D occultedRect = screenRect.Intersect( occultingScreenRect );
616  double topExposed = occultedRect.GetTop() - screenRect.GetTop();
617  double bottomExposed = screenRect.GetBottom() - occultedRect.GetBottom();
618  double leftExposed = occultedRect.GetLeft() - screenRect.GetLeft();
619  double rightExposed = screenRect.GetRight() - occultedRect.GetRight();
620 
621  if( std::max( topExposed, bottomExposed ) > std::max( leftExposed, rightExposed ) )
622  {
623  if( topExposed > bottomExposed )
624  center.y += ToWorld( screenRect.GetHeight() / 2 - topExposed / 2 );
625  else
626  center.y -= ToWorld( screenRect.GetHeight() / 2 - bottomExposed / 2 );
627  }
628  else
629  {
630  if( leftExposed > rightExposed )
631  center.x += ToWorld( screenRect.GetWidth() / 2 - leftExposed / 2 );
632  else
633  center.x -= ToWorld( screenRect.GetWidth() / 2 - rightExposed / 2 );
634  }
635 
636  SetCenter( center );
637 }
638 
639 
640 void VIEW::SetLayerOrder( int aLayer, int aRenderingOrder )
641 {
642  m_layers[aLayer].renderingOrder = aRenderingOrder;
643 
644  sortLayers();
645 }
646 
647 
648 int VIEW::GetLayerOrder( int aLayer ) const
649 {
650  return m_layers.at( aLayer ).renderingOrder;
651 }
652 
653 
654 void VIEW::SortLayers( int aLayers[], int& aCount ) const
655 {
656  int maxLay, maxOrd, maxIdx;
657 
658  for( int i = 0; i < aCount; ++i )
659  {
660  maxLay = aLayers[i];
661  maxOrd = GetLayerOrder( maxLay );
662  maxIdx = i;
663 
664  // Look for the max element in the range (j..aCount)
665  for( int j = i; j < aCount; ++j )
666  {
667  if( maxOrd < GetLayerOrder( aLayers[j] ) )
668  {
669  maxLay = aLayers[j];
670  maxOrd = GetLayerOrder( maxLay );
671  maxIdx = j;
672  }
673  }
674 
675  // Swap elements
676  aLayers[maxIdx] = aLayers[i];
677  aLayers[i] = maxLay;
678  }
679 }
680 
681 
682 void VIEW::ReorderLayerData( std::unordered_map<int, int> aReorderMap )
683 {
684  std::vector<VIEW_LAYER> new_map;
685  new_map.reserve( m_layers.size() );
686 
687  for( int ii = 0; ii < VIEW_MAX_LAYERS; ++ii )
688  new_map.emplace_back();
689 
690  for( const VIEW_LAYER& layer : m_layers )
691  {
692  int orig_idx = layer.id;
693  int new_idx = orig_idx;
694 
695  if( aReorderMap.count( orig_idx ) )
696  new_idx = aReorderMap.at( orig_idx );
697 
698  new_map[new_idx] = layer;
699  new_map[new_idx].id = new_idx;
700  }
701 
702  m_layers = new_map;
703 
704  for( VIEW_ITEM* item : *m_allItems )
705  {
706  VIEW_ITEM_DATA* viewData = item->viewPrivData();
707 
708  if( !viewData )
709  continue;
710 
711  int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
712 
713  item->ViewGetLayers( layers, layers_count );
714  viewData->saveLayers( layers, layers_count );
715 
716  viewData->reorderGroups( aReorderMap );
717 
718  viewData->m_requiredUpdate |= COLOR;
719  }
720 
721  UpdateItems();
722 }
723 
724 
726 {
727  UPDATE_COLOR_VISITOR( int aLayer, PAINTER* aPainter, GAL* aGal ) :
728  layer( aLayer ),
729  painter( aPainter ),
730  gal( aGal )
731  {
732  }
733 
734  bool operator()( VIEW_ITEM* aItem )
735  {
736  // Obtain the color that should be used for coloring the item
737  const COLOR4D color = painter->GetSettings()->GetColor( aItem, layer );
738  int group = aItem->viewPrivData()->getGroup( layer );
739 
740  if( group >= 0 )
742 
743  return true;
744  }
745 
746  int layer;
749 };
750 
751 
752 void VIEW::UpdateLayerColor( int aLayer )
753 {
754  // There is no point in updating non-cached layers
755  if( !IsCached( aLayer ) )
756  return;
757 
758  BOX2I r;
759 
760  r.SetMaximum();
761 
762  if( m_gal->IsVisible() )
763  {
764  GAL_UPDATE_CONTEXT ctx( m_gal );
765 
766  UPDATE_COLOR_VISITOR visitor( aLayer, m_painter, m_gal );
767  m_layers[aLayer].items->Query( r, visitor );
768  MarkTargetDirty( m_layers[aLayer].target );
769  }
770 }
771 
772 
774 {
775  if( m_gal->IsVisible() )
776  {
777  GAL_UPDATE_CONTEXT ctx( m_gal );
778 
779  for( VIEW_ITEM* item : *m_allItems )
780  {
781  VIEW_ITEM_DATA* viewData = item->viewPrivData();
782 
783  if( !viewData )
784  continue;
785 
786  int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
787  viewData->getLayers( layers, layers_count );
788 
789  for( int i = 0; i < layers_count; ++i )
790  {
791  const COLOR4D color = m_painter->GetSettings()->GetColor( item, layers[i] );
792  int group = viewData->getGroup( layers[i] );
793 
794  if( group >= 0 )
796  }
797  }
798  }
799 
800  MarkDirty();
801 }
802 
803 
805 {
806  UPDATE_DEPTH_VISITOR( int aLayer, int aDepth, GAL* aGal ) :
807  layer( aLayer ),
808  depth( aDepth ),
809  gal( aGal )
810  {
811  }
812 
813  bool operator()( VIEW_ITEM* aItem )
814  {
815  int group = aItem->viewPrivData()->getGroup( layer );
816 
817  if( group >= 0 )
819 
820  return true;
821  }
822 
823  int layer, depth;
825 };
826 
827 
828 int VIEW::GetTopLayer() const
829 {
830  if( m_topLayers.size() == 0 )
831  return 0;
832 
833  return *m_topLayers.begin();
834 }
835 
836 
837 void VIEW::SetTopLayer( int aLayer, bool aEnabled )
838 {
839  if( aEnabled )
840  {
841  if( m_topLayers.count( aLayer ) == 1 )
842  return;
843 
844  m_topLayers.insert( aLayer );
845 
846  // Move the layer closer to front
848  m_layers[aLayer].renderingOrder += TOP_LAYER_MODIFIER;
849  }
850  else
851  {
852  if( m_topLayers.count( aLayer ) == 0 )
853  return;
854 
855  m_topLayers.erase( aLayer );
856 
857  // Restore the previous rendering order
859  m_layers[aLayer].renderingOrder -= TOP_LAYER_MODIFIER;
860  }
861 }
862 
863 
864 void VIEW::EnableTopLayer( bool aEnable )
865 {
866  if( aEnable == m_enableOrderModifier )
867  return;
868 
869  m_enableOrderModifier = aEnable;
870 
871  std::set<unsigned int>::iterator it;
872 
873  if( aEnable )
874  {
875  for( it = m_topLayers.begin(); it != m_topLayers.end(); ++it )
876  m_layers[*it].renderingOrder += TOP_LAYER_MODIFIER;
877  }
878  else
879  {
880  for( it = m_topLayers.begin(); it != m_topLayers.end(); ++it )
881  m_layers[*it].renderingOrder -= TOP_LAYER_MODIFIER;
882  }
883 
886 }
887 
888 
890 {
891  std::set<unsigned int>::iterator it;
892 
894  {
895  // Restore the previous rendering order for layers that were marked as top
896  for( it = m_topLayers.begin(); it != m_topLayers.end(); ++it )
897  m_layers[*it].renderingOrder -= TOP_LAYER_MODIFIER;
898  }
899 
900  m_topLayers.clear();
901 }
902 
903 
905 {
906  sortLayers();
907 
908  if( m_gal->IsVisible() )
909  {
910  GAL_UPDATE_CONTEXT ctx( m_gal );
911 
912  for( VIEW_ITEM* item : *m_allItems )
913  {
914  VIEW_ITEM_DATA* viewData = item->viewPrivData();
915 
916  if( !viewData )
917  continue;
918 
919  int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
920  viewData->getLayers( layers, layers_count );
921 
922  for( int i = 0; i < layers_count; ++i )
923  {
924  int group = viewData->getGroup( layers[i] );
925 
926  if( group >= 0 )
927  m_gal->ChangeGroupDepth( group, m_layers[layers[i]].renderingOrder );
928  }
929  }
930  }
931 
932  MarkDirty();
933 }
934 
935 
937 {
938  DRAW_ITEM_VISITOR( VIEW* aView, int aLayer, bool aUseDrawPriority, bool aReverseDrawOrder ) :
939  view( aView ),
940  layer( aLayer ),
941  useDrawPriority( aUseDrawPriority ),
942  reverseDrawOrder( aReverseDrawOrder )
943  {
944  }
945 
946  bool operator()( VIEW_ITEM* aItem )
947  {
948  wxCHECK( aItem->viewPrivData(), false );
949 
950  // Conditions that have to be fulfilled for an item to be drawn
951  bool drawCondition = aItem->viewPrivData()->isRenderable() &&
952  aItem->ViewGetLOD( layer, view ) < view->m_scale;
953  if( !drawCondition )
954  return true;
955 
956  if( useDrawPriority )
957  drawItems.push_back( aItem );
958  else
959  view->draw( aItem, layer );
960 
961  return true;
962  }
963 
965  {
966  if( reverseDrawOrder )
967  std::sort( drawItems.begin(), drawItems.end(),
968  []( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool {
969  return b->viewPrivData()->m_drawPriority < a->viewPrivData()->m_drawPriority;
970  });
971  else
972  std::sort( drawItems.begin(), drawItems.end(),
973  []( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool {
974  return a->viewPrivData()->m_drawPriority < b->viewPrivData()->m_drawPriority;
975  });
976 
977  for( VIEW_ITEM* item : drawItems )
978  view->draw( item, layer );
979  }
980 
984  std::vector<VIEW_ITEM*> drawItems;
985 };
986 
987 
988 void VIEW::redrawRect( const BOX2I& aRect )
989 {
990  for( VIEW_LAYER* l : m_orderedLayers )
991  {
992  if( l->visible && IsTargetDirty( l->target ) && areRequiredLayersEnabled( l->id ) )
993  {
994  DRAW_ITEM_VISITOR drawFunc( this, l->id, m_useDrawPriority, m_reverseDrawOrder );
995 
996  m_gal->SetTarget( l->target );
997  m_gal->SetLayerDepth( l->renderingOrder );
998  l->items->Query( aRect, drawFunc );
999 
1000  if( m_useDrawPriority )
1001  drawFunc.deferredDraw();
1002  }
1003  }
1004 }
1005 
1006 
1007 void VIEW::draw( VIEW_ITEM* aItem, int aLayer, bool aImmediate )
1008 {
1009  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1010 
1011  if( !viewData )
1012  return;
1013 
1014  if( IsCached( aLayer ) && !aImmediate )
1015  {
1016  // Draw using cached information or create one
1017  int group = viewData->getGroup( aLayer );
1018 
1019  if( group >= 0 )
1020  m_gal->DrawGroup( group );
1021  else
1022  Update( aItem );
1023  }
1024  else
1025  {
1026  // Immediate mode
1027  if( !m_painter->Draw( aItem, aLayer ) )
1028  aItem->ViewDraw( aLayer, this ); // Alternative drawing method
1029  }
1030 }
1031 
1032 
1033 void VIEW::draw( VIEW_ITEM* aItem, bool aImmediate )
1034 {
1035  int layers[VIEW_MAX_LAYERS], layers_count;
1036 
1037  aItem->ViewGetLayers( layers, layers_count );
1038 
1039  // Sorting is needed for drawing order dependent GALs (like Cairo)
1040  SortLayers( layers, layers_count );
1041 
1042  for( int i = 0; i < layers_count; ++i )
1043  {
1044  m_gal->SetLayerDepth( m_layers.at( layers[i] ).renderingOrder );
1045  draw( aItem, layers[i], aImmediate );
1046  }
1047 }
1048 
1049 
1050 void VIEW::draw( VIEW_GROUP* aGroup, bool aImmediate )
1051 {
1052  for( unsigned int i = 0; i < aGroup->GetSize(); i++)
1053  draw( aGroup->GetItem(i), aImmediate );
1054 }
1055 
1056 
1058 {
1059  RECACHE_ITEM_VISITOR( VIEW* aView, GAL* aGal, int aLayer ) :
1060  view( aView ),
1061  gal( aGal ),
1062  layer( aLayer )
1063  {
1064  }
1065 
1066  bool operator()( VIEW_ITEM* aItem )
1067  {
1068  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1069 
1070  if( !viewData )
1071  return false;
1072 
1073  // Remove previously cached group
1074  int group = viewData->getGroup( layer );
1075 
1076  if( group >= 0 )
1077  gal->DeleteGroup( group );
1078 
1079  viewData->setGroup( layer, -1 );
1080  view->Update( aItem );
1081 
1082  return true;
1083  }
1084 
1087  int layer;
1088 };
1089 
1090 
1092 {
1093  BOX2I r;
1094  r.SetMaximum();
1095  m_allItems->clear();
1096 
1097  for( VIEW_LAYER& layer : m_layers )
1098  layer.items->RemoveAll();
1099 
1100  m_nextDrawPriority = 0;
1101 
1102  m_gal->ClearCache();
1103 }
1104 
1105 
1107 {
1109  {
1110  // TARGET_CACHED and TARGET_NONCACHED have to be redrawn together, as they contain
1111  // layers that rely on each other (eg. netnames are noncached, but tracks - are cached)
1114 
1115  MarkDirty();
1116  }
1117 
1118  if( IsTargetDirty( TARGET_OVERLAY ) )
1119  {
1121  }
1122 }
1123 
1124 
1126 {
1127 #ifdef KICAD_GAL_PROFILE
1128  PROF_COUNTER totalRealTime;
1129 #endif /* KICAD_GAL_PROFILE */
1130 
1131  VECTOR2D screenSize = m_gal->GetScreenPixelSize();
1132  BOX2D rect( ToWorld( VECTOR2D( 0, 0 ) ),
1133  ToWorld( screenSize ) - ToWorld( VECTOR2D( 0, 0 ) ) );
1134 
1135  rect.Normalize();
1136  BOX2I recti( rect.GetPosition(), rect.GetSize() );
1137 
1138  // The view rtree uses integer positions. Large screens can overflow
1139  // this size so in this case, simply set the rectangle to the full rtree
1140  if( rect.GetWidth() > std::numeric_limits<int>::max() ||
1141  rect.GetHeight() > std::numeric_limits<int>::max() )
1142  recti.SetMaximum();
1143 
1144  redrawRect( recti );
1145  // All targets were redrawn, so nothing is dirty
1149 
1150 #ifdef KICAD_GAL_PROFILE
1151  totalRealTime.Stop();
1152  wxLogTrace( traceGalProfile, "VIEW::Redraw(): %.1f ms", totalRealTime.msecs() );
1153 #endif /* KICAD_GAL_PROFILE */
1154 }
1155 
1156 
1158 {
1159  return m_gal->GetScreenPixelSize();
1160 }
1161 
1162 
1164 {
1166  view( aView )
1167  {
1168  }
1169 
1170  bool operator()( VIEW_ITEM* aItem )
1171  {
1172  aItem->viewPrivData()->deleteGroups();
1173 
1174  return true;
1175  }
1176 
1178 };
1179 
1180 
1182 {
1183  BOX2I r;
1184 
1185  r.SetMaximum();
1186  CLEAR_LAYER_CACHE_VISITOR visitor( this );
1187 
1188  for( VIEW_LAYER& layer : m_layers )
1189  layer.items->Query( r, visitor );
1190 }
1191 
1192 
1193 void VIEW::invalidateItem( VIEW_ITEM* aItem, int aUpdateFlags )
1194 {
1195  if( aUpdateFlags & INITIAL_ADD )
1196  {
1197  // Don't update layers or bbox, since it was done in VIEW::Add()
1198  // Now that we have initialized, set flags to ALL for the code below
1199  aUpdateFlags = ALL;
1200  }
1201  else
1202  {
1203  // updateLayers updates geometry too, so we do not have to update both of them at the
1204  // same time
1205  if( aUpdateFlags & LAYERS )
1206  {
1207  updateLayers( aItem );
1208  }
1209  else if( aUpdateFlags & GEOMETRY )
1210  {
1211  updateBbox( aItem );
1212  }
1213  }
1214 
1215  int layers[VIEW_MAX_LAYERS], layers_count;
1216  aItem->ViewGetLayers( layers, layers_count );
1217 
1218  // Iterate through layers used by the item and recache it immediately
1219  for( int i = 0; i < layers_count; ++i )
1220  {
1221  int layerId = layers[i];
1222 
1223  if( IsCached( layerId ) )
1224  {
1225  if( aUpdateFlags & ( GEOMETRY | LAYERS | REPAINT ) )
1226  updateItemGeometry( aItem, layerId );
1227  else if( aUpdateFlags & COLOR )
1228  updateItemColor( aItem, layerId );
1229  }
1230 
1231  // Mark those layers as dirty, so the VIEW will be refreshed
1232  MarkTargetDirty( m_layers[layerId].target );
1233  }
1234 
1235  aItem->viewPrivData()->clearUpdateFlags();
1236 }
1237 
1238 
1240 {
1241  int n = 0;
1242 
1243  m_orderedLayers.resize( m_layers.size() );
1244 
1245  for( VIEW_LAYER& layer : m_layers )
1246  m_orderedLayers[n++] = &layer;
1247 
1248  sort( m_orderedLayers.begin(), m_orderedLayers.end(), compareRenderingOrder );
1249 
1250  MarkDirty();
1251 }
1252 
1253 
1254 void VIEW::updateItemColor( VIEW_ITEM* aItem, int aLayer )
1255 {
1256  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1257  wxCHECK( (unsigned) aLayer < m_layers.size(), /*void*/ );
1258  wxCHECK( IsCached( aLayer ), /*void*/ );
1259 
1260  if( !viewData )
1261  return;
1262 
1263  // Obtain the color that should be used for coloring the item on the specific layerId
1264  const COLOR4D color = m_painter->GetSettings()->GetColor( aItem, aLayer );
1265  int group = viewData->getGroup( aLayer );
1266 
1267  // Change the color, only if it has group assigned
1268  if( group >= 0 )
1270 }
1271 
1272 
1273 void VIEW::updateItemGeometry( VIEW_ITEM* aItem, int aLayer )
1274 {
1275  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1276  wxCHECK( (unsigned) aLayer < m_layers.size(), /*void*/ );
1277  wxCHECK( IsCached( aLayer ), /*void*/ );
1278 
1279  if( !viewData )
1280  return;
1281 
1282  VIEW_LAYER& l = m_layers.at( aLayer );
1283 
1284  m_gal->SetTarget( l.target );
1286 
1287  // Redraw the item from scratch
1288  int group = viewData->getGroup( aLayer );
1289 
1290  if( group >= 0 )
1291  m_gal->DeleteGroup( group );
1292 
1293  group = m_gal->BeginGroup();
1294  viewData->setGroup( aLayer, group );
1295 
1296  if( !m_painter->Draw( static_cast<EDA_ITEM*>( aItem ), aLayer ) )
1297  aItem->ViewDraw( aLayer, this ); // Alternative drawing method
1298 
1299  m_gal->EndGroup();
1300 }
1301 
1302 
1304 {
1305  int layers[VIEW_MAX_LAYERS], layers_count;
1306 
1307  aItem->ViewGetLayers( layers, layers_count );
1308 
1309  for( int i = 0; i < layers_count; ++i )
1310  {
1311  VIEW_LAYER& l = m_layers[layers[i]];
1312  l.items->Remove( aItem );
1313  l.items->Insert( aItem );
1314  MarkTargetDirty( l.target );
1315  }
1316 }
1317 
1318 
1320 {
1321  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1322  int layers[VIEW_MAX_LAYERS], layers_count;
1323 
1324  if( !viewData )
1325  return;
1326 
1327  // Remove the item from previous layer set
1328  viewData->getLayers( layers, layers_count );
1329 
1330  for( int i = 0; i < layers_count; ++i )
1331  {
1332  VIEW_LAYER& l = m_layers[layers[i]];
1333  l.items->Remove( aItem );
1334  MarkTargetDirty( l.target );
1335 
1336  if( IsCached( l.id ) )
1337  {
1338  // Redraw the item from scratch
1339  int prevGroup = viewData->getGroup( layers[i] );
1340 
1341  if( prevGroup >= 0 )
1342  {
1343  m_gal->DeleteGroup( prevGroup );
1344  viewData->setGroup( l.id, -1 );
1345  }
1346  }
1347  }
1348 
1349  // Add the item to new layer set
1350  aItem->ViewGetLayers( layers, layers_count );
1351  viewData->saveLayers( layers, layers_count );
1352 
1353  for( int i = 0; i < layers_count; i++ )
1354  {
1355  VIEW_LAYER& l = m_layers[layers[i]];
1356  l.items->Insert( aItem );
1357  MarkTargetDirty( l.target );
1358  }
1359 }
1360 
1361 
1362 bool VIEW::areRequiredLayersEnabled( int aLayerId ) const
1363 {
1364  wxCHECK( (unsigned) aLayerId < m_layers.size(), false );
1365 
1366  std::set<int>::const_iterator it, it_end;
1367 
1368  for( it = m_layers.at( aLayerId ).requiredLayers.begin(),
1369  it_end = m_layers.at( aLayerId ).requiredLayers.end(); it != it_end; ++it )
1370  {
1371  // That is enough if just one layer is not enabled
1372  if( !m_layers.at( *it ).visible || !areRequiredLayersEnabled( *it ) )
1373  return false;
1374  }
1375 
1376  return true;
1377 }
1378 
1379 
1381 {
1382  BOX2I r;
1383 
1384  r.SetMaximum();
1385 
1386  for( const VIEW_LAYER& l : m_layers )
1387  {
1388  if( IsCached( l.id ) )
1389  {
1390  RECACHE_ITEM_VISITOR visitor( this, m_gal, l.id );
1391  l.items->Query( r, visitor );
1392  }
1393  }
1394 }
1395 
1396 
1398 {
1399  if( m_gal->IsVisible() )
1400  {
1401  GAL_UPDATE_CONTEXT ctx( m_gal );
1402 
1403  for( VIEW_ITEM* item : *m_allItems )
1404  {
1405  if( item->viewPrivData() && item->viewPrivData()->m_requiredUpdate != NONE )
1406  {
1407  invalidateItem( item, item->viewPrivData()->m_requiredUpdate );
1408  item->viewPrivData()->m_requiredUpdate = NONE;
1409  }
1410  }
1411  }
1412 }
1413 
1414 
1415 void VIEW::UpdateAllItems( int aUpdateFlags )
1416 {
1417  for( VIEW_ITEM* item : *m_allItems )
1418  {
1419  if( item->viewPrivData() )
1420  item->viewPrivData()->m_requiredUpdate |= aUpdateFlags;
1421  }
1422 }
1423 
1424 
1425 void VIEW::UpdateAllItemsConditionally( int aUpdateFlags,
1426  std::function<bool( VIEW_ITEM* )> aCondition )
1427 {
1428  for( VIEW_ITEM* item : *m_allItems )
1429  {
1430  if( aCondition( item ) )
1431  {
1432  if( item->viewPrivData() )
1433  item->viewPrivData()->m_requiredUpdate |= aUpdateFlags;
1434  }
1435  }
1436 }
1437 
1438 
1439 std::unique_ptr<VIEW> VIEW::DataReference() const
1440 {
1441  std::unique_ptr<VIEW> ret = std::make_unique<VIEW>();
1442  ret->m_allItems = m_allItems;
1443  ret->m_layers = m_layers;
1444  ret->sortLayers();
1445  return ret;
1446 }
1447 
1448 
1449 void VIEW::SetVisible( VIEW_ITEM* aItem, bool aIsVisible )
1450 {
1451  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1452 
1453  if( !viewData )
1454  return;
1455 
1456  bool cur_visible = viewData->m_flags & VISIBLE;
1457 
1458  if( cur_visible != aIsVisible )
1459  {
1460  if( aIsVisible )
1461  viewData->m_flags |= VISIBLE;
1462  else
1463  viewData->m_flags &= ~VISIBLE;
1464 
1465  Update( aItem, APPEARANCE | COLOR );
1466  }
1467 }
1468 
1469 
1470 void VIEW::Hide( VIEW_ITEM* aItem, bool aHide )
1471 {
1472  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1473 
1474  if( !viewData )
1475  return;
1476 
1477  if( !( viewData->m_flags & VISIBLE ) )
1478  return;
1479 
1480  if( aHide )
1481  viewData->m_flags |= HIDDEN;
1482  else
1483  viewData->m_flags &= ~HIDDEN;
1484 
1485  Update( aItem, APPEARANCE );
1486 }
1487 
1488 
1489 bool VIEW::IsVisible( const VIEW_ITEM* aItem ) const
1490 {
1491  const VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1492 
1493  return viewData && ( viewData->m_flags & VISIBLE );
1494 }
1495 
1496 
1497 void VIEW::Update( const VIEW_ITEM* aItem ) const
1498 {
1499  Update( aItem, ALL );
1500 }
1501 
1502 
1503 void VIEW::Update( const VIEW_ITEM* aItem, int aUpdateFlags ) const
1504 {
1505  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1506 
1507  if( !viewData )
1508  return;
1509 
1510  assert( aUpdateFlags != NONE );
1511 
1512  viewData->m_requiredUpdate |= aUpdateFlags;
1513 }
1514 
1515 
1516 std::shared_ptr<VIEW_OVERLAY> VIEW::MakeOverlay()
1517 {
1518  std::shared_ptr<VIEW_OVERLAY> overlay( new VIEW_OVERLAY );
1519 
1520  Add( overlay.get() );
1521  return overlay;
1522 }
1523 
1524 
1526 {
1527  if( !m_preview )
1528  return;
1529 
1530  m_preview->Clear();
1531 
1532  for( EDA_ITEM *item : m_ownedItems )
1533  delete item;
1534 
1535  m_ownedItems.clear();
1536  Update( m_preview.get() );
1537 }
1538 
1539 
1541 {
1542  m_preview.reset( new KIGFX::VIEW_GROUP() );
1543  Add( m_preview.get() );
1544 }
1545 
1546 
1547 void VIEW::AddToPreview( EDA_ITEM* aItem, bool aTakeOwnership )
1548 {
1549  Hide( aItem, false );
1550  m_preview->Add( aItem );
1551 
1552  if( aTakeOwnership )
1553  m_ownedItems.push_back( aItem );
1554 
1555  SetVisible( m_preview.get(), true );
1556  Hide( m_preview.get(), false );
1557  Update( m_preview.get() );
1558 }
1559 
1560 
1561 void VIEW::ShowPreview( bool aShow )
1562 {
1563  SetVisible( m_preview.get(), aShow );
1564 }
1565 
1566 
1567 const int VIEW::TOP_LAYER_MODIFIER = -VIEW_MAX_LAYERS;
1568 
1569 } // 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:1470
virtual void DrawGroup(int aGroupNumber)
Draw the stored group.
Item is being added to the view.
Definition: view_item.h:56
Item is temporarily hidden (e.g.
Definition: view_item.h:66
int requiredUpdate() const
Return current update flag for an item.
Definition: view.cpp:208
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:513
VIEW_ITEM_DATA * m_viewPrivData
Definition: view_item.h:156
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition: view.cpp:525
void updateLayers(VIEW_ITEM *aItem)
Determine rendering order of layers. Used in display order sorting function.
Definition: view.cpp:1319
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:1425
CONTAINER & m_cont
Definition: view.cpp:422
void SetLayerOrder(int aLayer, int aRenderingOrder)
Set rendering order of a particular layer.
Definition: view.cpp:640
void SetRequired(int aLayerId, int aRequiredId, bool aRequired=true)
Mark the aRequiredId layer as required for the aLayerId layer.
Definition: view.cpp:391
void updateItemColor(VIEW_ITEM *aItem, int aLayer)
Update all information needed to draw an item.
Definition: view.cpp:1254
bool m_useDrawPriority
The next sequential drawing priority.
Definition: view.h:838
std::unique_ptr< KIGFX::VIEW_GROUP > m_preview
Definition: view.h:780
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:191
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:837
static const int TOP_LAYER_MODIFIER
Flag to respect draw priority when drawing items.
Definition: view.h:835
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:1239
int getFlags() const
Definition: view.cpp:67
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:450
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:1547
int color
Definition: DXF_plotter.cpp:60
void RecacheAllItems()
Rebuild GAL display lists.
Definition: view.cpp:1380
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition: view.cpp:1415
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:351
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:946
void SetFlip(bool xAxis, bool yAxis)
Sets flipping of the screen.
void InitPreview()
Definition: view.cpp:1540
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:1170
GAL * m_gal
Dynamic VIEW (eg.
Definition: view.h:825
bool areRequiredLayersEnabled(int aLayerId) const
Definition: view.cpp:1362
coord_type GetRight() const
Definition: box2.h:182
QUERY_VISITOR(CONTAINER &aCont, int aLayer)
Definition: view.cpp:409
std::set< unsigned int > m_topLayers
Center point of the VIEW (the point at which we are looking at).
Definition: view.h:798
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:216
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:904
Visibility flag has changed.
Definition: view_item.h:52
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:1066
coord_type GetBottom() const
Definition: box2.h:183
void SetMirror(bool aMirrorX, bool aMirrorY)
Control the mirroring of the VIEW.
Definition: view.cpp:540
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:81
Color has changed.
Definition: view_item.h:53
All except INITIAL_ADD.
Definition: view_item.h:58
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:87
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:1516
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:864
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
Scale of displayed VIEW_ITEMs.
Definition: view.h:801
VIEW * m_view
Current dynamic view the item is assigned to.
Definition: view.cpp:230
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:414
static constexpr int VIEW_MAX_LAYERS
maximum number of layers that may be shown
Definition: view.h:680
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:795
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:654
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:1561
UPDATE_COLOR_VISITOR(int aLayer, PAINTER *aPainter, GAL *aGal)
Definition: view.cpp:727
double m_minScale
Scale upper limit.
Definition: view.h:810
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:81
int layers[VIEW_MAX_LAYERS]
Definition: view.cpp:982
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:57
VIEW_ITEM class definition.
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:579
UPDATE_DEPTH_VISITOR(int aLayer, int aDepth, GAL *aGal)
Definition: view.cpp:806
VECTOR2< double > VECTOR2D
Definition: vector2d.h:622
virtual void Redraw()
Immediately redraws the whole view.
Definition: view.cpp:1125
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition: view.h:572
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:561
void Clear()
Remove all items from the view.
Definition: view.cpp:1091
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition: view.cpp:1489
VIEW_ITEM_DATA * viewPrivData() const
Definition: view_item.h:143
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:734
virtual int GetTopLayer() const
Definition: view.cpp:828
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
Vertical flip flag.
Definition: view.h:816
void invalidateItem(VIEW_ITEM *aItem, int aUpdateFlags)
Manage dirty flags & redraw queuing when updating an item.
Definition: view.cpp:1193
void ClearPreview()
Definition: view.cpp:1525
const VECTOR2I & GetScreenPixelSize() const
Return the size of the our rendering area in pixels.
Definition: view.cpp:1157
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:689
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:682
void UpdateItems()
Iterate through the list of items that asked for updating and updates them.
Definition: view.cpp:1397
void markTargetClean(int aTarget)
Definition: view.h:702
GroupPair * m_groups
Definition: view.cpp:240
void updateBbox(VIEW_ITEM *aItem)
Update set of layers that an item occupies.
Definition: view.cpp:1303
PAINTER * m_painter
Interface to #PAINTER that is used to draw items.
Definition: view.h:822
bool m_reverseDrawOrder
Definition: view.h:844
Item is visible (in general)
Definition: view_item.h:65
int m_nextDrawPriority
Flag to reverse the draw order when using draw priority.
Definition: view.h:841
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:469
void saveLayers(int *aLayers, int aCount)
Save layers used by the item.
Definition: view.cpp:192
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:813
std::vector< VIEW_LAYER > m_layers
Sorted list of pointers to members of m_layers.
Definition: view.h:789
void ClearTopLayers()
Remove all layers from the on-the-top set (they are no longer displayed over the rest of layers).
Definition: view.cpp:889
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:553
void clearGroupCache()
Definition: view.cpp:1181
double m_maxScale
Horizontal flip flag.
Definition: view.h:813
void UpdateLayerColor(int aLayer)
Apply the new coloring scheme held by RENDER_SETTINGS in case that it has changed.
Definition: view.cpp:752
std::unique_ptr< VIEW > DataReference() const
Return a new VIEW object that shares the same set of VIEW_ITEMs and LAYERs.
Definition: view.cpp:1439
No updates are required.
Definition: view_item.h:51
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:407
void redrawRect(const BOX2I &aRect)
Definition: view.cpp:988
bool isRenderable() const
Return if the item should be drawn or not.
Definition: view.cpp:224
std::vector< EDA_ITEM * > m_ownedItems
Whether to use rendering order modifier or not.
Definition: view.h:783
void updateItemGeometry(VIEW_ITEM *aItem, int aLayer)
Update bounding box of an item.
Definition: view.cpp:1273
Board layer functions and definitions.
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:786
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:248
BOX2D m_boundary
Scale lower limit.
Definition: view.h:807
std::vector< VIEW_LAYER * > m_orderedLayers
Flat list of all items.
Definition: view.h:792
std::pair< VIEW_ITEM *, int > LAYER_ITEM_PAIR
Definition: view.h:72
int GetLayerOrder(int aLayer) const
Return rendering order of a particular layer.
Definition: view.cpp:648
void draw(VIEW_ITEM *aItem, int aLayer, bool aImmediate=false)
Draw an item, but on a specified layers.
Definition: view.cpp:1007
bool IsCached(int aLayer) const
Return true if the layer is cached.
Definition: view.h:579
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:819
void ClearTargets()
Clear targets that are marked as dirty.
Definition: view.cpp:1106
coord_type GetHeight() const
Definition: box2.h:181
int m_flags
Visibility flags.
Definition: view.cpp:231
void ClearViewPrivData()
Definition: view_item.h:148
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1449
void CopySettings(const VIEW *aOtherView)
Copy layers and visibility settings from another view.
Definition: view.cpp:488
double m_scale
View boundaries.
Definition: view.h:804
Layers have changed.
Definition: view_item.h:55
int renderingOrder
Rendering order of this layer.
Definition: view.h:688
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:321
std::pair< int, int > GroupPair
Indexes of cached GAL display lists corresponding to the item (for every layer it.
Definition: view.cpp:236
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:427
coord_type GetLeft() const
Definition: box2.h:186
virtual ~VIEW()
Definition: view.cpp:315
VIEW(bool aIsDynamic=true)
Definition: view.cpp:263
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:67
DRAW_ITEM_VISITOR(VIEW *aView, int aLayer, bool aUseDrawPriority, bool aReverseDrawOrder)
Definition: view.cpp:938
const MATRIX3x3D & GetWorldScreenMatrix() const
Get the world <-> screen transformation matrix.
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition: view.cpp:773
double GetScale() const
Definition: view.h:263
std::vector< int > m_layers
Stores layer numbers used by the item.
Definition: view.cpp:244
void SetGAL(GAL *aGal)
Assign a rendering device for the VIEW.
Definition: view.cpp:494
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:767
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:596
virtual double ViewGetLOD(int aLayer, VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition: view_item.h:137
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:1503
std::vector< VIEW_ITEM * > drawItems
Definition: view.cpp:984
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:54
RECACHE_ITEM_VISITOR(VIEW *aView, GAL *aGal, int aLayer)
Definition: view.cpp:1059
virtual void ViewDraw(int aLayer, VIEW *aView) const
Draw the parts of the object belonging to layer aLayer.
Definition: view_item.h:111
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103
BOX2< Vec > Intersect(const BOX2< Vec > &aRect)
Return the intersection of this with another rectangle.
Definition: box2.h:248
RENDER_TARGET target
Where the layer should be rendered.
Definition: view.h:690
std::shared_ptr< VIEW_RTREE > items
R-tree indexing all items on this layer.
Definition: view.h:687