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