KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 if( aItem->m_viewPrivData )
244 {
245 if( aItem->m_viewPrivData->m_view )
246 aItem->m_viewPrivData->m_view->VIEW::Remove( aItem );
247
248 delete aItem->m_viewPrivData;
249 aItem->m_viewPrivData = nullptr;
250 }
251}
252
253
254VIEW::VIEW( bool aIsDynamic ) :
255 m_enableOrderModifier( true ),
256 m_scale( 4.0 ),
257 m_minScale( 0.2 ), m_maxScale( 50000.0 ),
258 m_mirrorX( false ), m_mirrorY( false ),
259 m_painter( nullptr ),
260 m_gal( nullptr ),
261 m_dynamic( aIsDynamic ),
262 m_useDrawPriority( false ),
263 m_nextDrawPriority( 0 ),
264 m_reverseDrawOrder( false )
265{
266 // Set m_boundary to define the max area size. The default area size
267 // is defined here as the max value of a int.
268 // this is a default value acceptable for Pcbnew and Gerbview, but too large for Eeschema.
269 // So in eeschema a call to SetBoundary() with a smaller value will be needed.
270 typedef std::numeric_limits<int> coord_limits;
271 double pos = coord_limits::lowest() / 2 + coord_limits::epsilon();
272 double size = coord_limits::max() - coord_limits::epsilon();
273 m_boundary.SetOrigin( pos, pos );
274 m_boundary.SetSize( size, size );
275
276 m_allItems.reset( new std::vector<VIEW_ITEM*> );
277 m_allItems->reserve( 32768 );
278
279 // Redraw everything at the beginning
280 MarkDirty();
281
282 m_layers.reserve( VIEW_MAX_LAYERS );
283
284 // View uses layers to display EDA_ITEMs (item may be displayed on several layers, for example
285 // pad may be shown on pad, pad hole and solder paste layers). There are usual copper layers
286 // (eg. F.Cu, B.Cu, internal and so on) and layers for displaying objects such as texts,
287 // silkscreen, pads, vias, etc.
288 for( int ii = 0; ii < VIEW_MAX_LAYERS; ++ii )
289 {
290 m_layers.emplace_back();
291 m_layers[ii].items = std::make_shared<VIEW_RTREE>();
292 m_layers[ii].id = ii;
293 m_layers[ii].renderingOrder = ii;
294 m_layers[ii].visible = true;
295 m_layers[ii].displayOnly = false;
296 m_layers[ii].diffLayer = false;
297 m_layers[ii].hasNegatives = false;
298 m_layers[ii].target = TARGET_CACHED;
299 }
300
301 sortLayers();
302
303 m_preview.reset( new KIGFX::VIEW_GROUP() );
304 Add( m_preview.get() );
305}
306
307
309{
310 Remove( m_preview.get() );
311}
312
313
314void VIEW::Add( VIEW_ITEM* aItem, int aDrawPriority )
315{
316 int layers[VIEW_MAX_LAYERS], layers_count;
317
318 if( aDrawPriority < 0 )
319 aDrawPriority = m_nextDrawPriority++;
320
321 if( !aItem->m_viewPrivData )
322 aItem->m_viewPrivData = new VIEW_ITEM_DATA;
323
324 wxASSERT_MSG( aItem->m_viewPrivData->m_view == nullptr
325 || aItem->m_viewPrivData->m_view == this,
326 wxS( "Already in a different view!" ) );
327
328 aItem->m_viewPrivData->m_view = this;
329 aItem->m_viewPrivData->m_drawPriority = aDrawPriority;
330
331 aItem->ViewGetLayers( layers, layers_count );
332 aItem->viewPrivData()->saveLayers( layers, layers_count );
333
334 m_allItems->push_back( aItem );
335
336 for( int i = 0; i < layers_count; ++i )
337 {
338 wxCHECK2_MSG( layers[i] >= 0 && static_cast<unsigned>( layers[i] ) < m_layers.size(),
339 continue, wxS( "Invalid layer" ) );
340
341 VIEW_LAYER& l = m_layers[layers[i]];
342 l.items->Insert( aItem );
344 }
345
346 SetVisible( aItem, true );
347 Update( aItem, KIGFX::INITIAL_ADD );
348}
349
350
352{
353 if( aItem && aItem->m_viewPrivData )
354 {
355 wxCHECK( aItem->m_viewPrivData->m_view == this, /*void*/ );
356 auto item = std::find( m_allItems->begin(), m_allItems->end(), aItem );
357
358 if( item != m_allItems->end() )
359 {
360 m_allItems->erase( item );
362 }
363
364 int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
365 aItem->m_viewPrivData->getLayers( layers, layers_count );
366
367 for( int i = 0; i < layers_count; ++i )
368 {
369 VIEW_LAYER& l = m_layers[layers[i]];
370 l.items->Remove( aItem );
372
373 // Clear the GAL cache
374 int prevGroup = aItem->m_viewPrivData->getGroup( layers[i] );
375
376 if( prevGroup >= 0 )
377 m_gal->DeleteGroup( prevGroup );
378 }
379
381 aItem->m_viewPrivData->m_view = nullptr;
382 }
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();
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 drawForcedTransparent( false ),
930 {
931 }
932
933 bool operator()( VIEW_ITEM* aItem )
934 {
935 wxCHECK( aItem->viewPrivData(), false );
936
938 {
940 return true;
941 }
942
943 // Conditions that have to be fulfilled for an item to be drawn
944 bool drawCondition = aItem->viewPrivData()->isRenderable()
945 && aItem->ViewGetLOD( layer, view ) < view->m_scale;
946 if( !drawCondition )
947 return true;
948
949 if( useDrawPriority )
950 drawItems.push_back( aItem );
951 else
952 view->draw( aItem, layer );
953
954 return true;
955 }
956
958 {
959 if( reverseDrawOrder )
960 {
961 std::sort( drawItems.begin(), drawItems.end(),
962 []( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool
963 {
964 return b->viewPrivData()->m_drawPriority < a->viewPrivData()->m_drawPriority;
965 } );
966 }
967 else
968 {
969 std::sort( drawItems.begin(), drawItems.end(),
970 []( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool
971 {
972 return a->viewPrivData()->m_drawPriority < b->viewPrivData()->m_drawPriority;
973 } );
974 }
975
976 for( VIEW_ITEM* item : drawItems )
977 view->draw( item, layer );
978 }
979
983 std::vector<VIEW_ITEM*> drawItems;
986};
987
988
989void VIEW::redrawRect( const BOX2I& aRect )
990{
991 for( VIEW_LAYER* l : m_orderedLayers )
992 {
993 if( l->visible && IsTargetDirty( l->target ) && areRequiredLayersEnabled( l->id ) )
994 {
996
997 m_gal->SetTarget( l->target );
998 m_gal->SetLayerDepth( l->renderingOrder );
999
1000 // Differential layer also work for the negatives, since both special layer types
1001 // will composite on separate layers (at least in Cairo)
1002 if( l->diffLayer )
1004 else if( l->hasNegatives )
1006
1007 l->items->Query( aRect, drawFunc );
1008
1009 if( m_useDrawPriority )
1010 drawFunc.deferredDraw();
1011
1012 if( l->diffLayer )
1014 else if( l->hasNegatives )
1016
1017 if( drawFunc.foundForcedTransparent )
1018 {
1019 drawFunc.drawForcedTransparent = true;
1020
1022 m_gal->EnableDepthTest( true );
1023 m_gal->SetLayerDepth( l->renderingOrder );
1024
1025 l->items->Query( aRect, drawFunc );
1026 }
1027 }
1028 }
1029}
1030
1031
1032void VIEW::draw( VIEW_ITEM* aItem, int aLayer, bool aImmediate )
1033{
1034 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1035
1036 if( !viewData )
1037 return;
1038
1039 if( IsCached( aLayer ) && !aImmediate )
1040 {
1041 // Draw using cached information or create one
1042 int group = viewData->getGroup( aLayer );
1043
1044 if( group >= 0 )
1045 m_gal->DrawGroup( group );
1046 else
1047 Update( aItem );
1048 }
1049 else
1050 {
1051 // Immediate mode
1052 if( !m_painter->Draw( aItem, aLayer ) )
1053 aItem->ViewDraw( aLayer, this ); // Alternative drawing method
1054 }
1055}
1056
1057
1058void VIEW::draw( VIEW_ITEM* aItem, bool aImmediate )
1059{
1060 int layers[VIEW_MAX_LAYERS], layers_count;
1061
1062 aItem->ViewGetLayers( layers, layers_count );
1063
1064 // Sorting is needed for drawing order dependent GALs (like Cairo)
1065 SortLayers( layers, layers_count );
1066
1067 for( int i = 0; i < layers_count; ++i )
1068 {
1069 m_gal->SetLayerDepth( m_layers.at( layers[i] ).renderingOrder );
1070 draw( aItem, layers[i], aImmediate );
1071 }
1072}
1073
1074
1075void VIEW::draw( VIEW_GROUP* aGroup, bool aImmediate )
1076{
1077 for( unsigned int i = 0; i < aGroup->GetSize(); i++)
1078 draw( aGroup->GetItem(i), aImmediate );
1079}
1080
1081
1083{
1084 RECACHE_ITEM_VISITOR( VIEW* aView, GAL* aGal, int aLayer ) :
1085 view( aView ),
1086 gal( aGal ),
1087 layer( aLayer )
1088 {
1089 }
1090
1091 bool operator()( VIEW_ITEM* aItem )
1092 {
1093 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1094
1095 if( !viewData )
1096 return false;
1097
1098 // Remove previously cached group
1099 int group = viewData->getGroup( layer );
1100
1101 if( group >= 0 )
1102 gal->DeleteGroup( group );
1103
1104 viewData->setGroup( layer, -1 );
1105 view->Update( aItem );
1106
1107 return true;
1108 }
1109
1113};
1114
1115
1117{
1118 BOX2I r;
1119 r.SetMaximum();
1120 m_allItems->clear();
1121
1122 for( VIEW_LAYER& layer : m_layers )
1123 layer.items->RemoveAll();
1124
1126
1127 m_gal->ClearCache();
1128}
1129
1130
1132{
1134 {
1135 // TARGET_CACHED and TARGET_NONCACHED have to be redrawn together, as they contain
1136 // layers that rely on each other (eg. netnames are noncached, but tracks - are cached)
1139
1140 MarkDirty();
1141 }
1142
1144 {
1146 }
1147}
1148
1149
1151{
1152#ifdef KICAD_GAL_PROFILE
1153 PROF_TIMER totalRealTime;
1154#endif /* KICAD_GAL_PROFILE */
1155
1156 VECTOR2D screenSize = m_gal->GetScreenPixelSize();
1157 BOX2D rect( ToWorld( VECTOR2D( 0, 0 ) ),
1158 ToWorld( screenSize ) - ToWorld( VECTOR2D( 0, 0 ) ) );
1159
1160 rect.Normalize();
1161 BOX2I recti( rect.GetPosition(), rect.GetSize() );
1162
1163 // The view rtree uses integer positions. Large screens can overflow this size so in
1164 // this case, simply set the rectangle to the full rtree.
1165 if( rect.GetWidth() > std::numeric_limits<int>::max()
1166 || rect.GetHeight() > std::numeric_limits<int>::max() )
1167 {
1168 recti.SetMaximum();
1169 }
1170
1171 redrawRect( recti );
1172
1173 // All targets were redrawn, so nothing is dirty
1174 MarkClean();
1175
1176#ifdef KICAD_GAL_PROFILE
1177 totalRealTime.Stop();
1178 wxLogTrace( traceGalProfile, wxS( "VIEW::Redraw(): %.1f ms" ), totalRealTime.msecs() );
1179#endif /* KICAD_GAL_PROFILE */
1180}
1181
1182
1184{
1185 return m_gal->GetScreenPixelSize();
1186}
1187
1188
1190{
1192 view( aView )
1193 {
1194 }
1195
1196 bool operator()( VIEW_ITEM* aItem )
1197 {
1198 aItem->viewPrivData()->deleteGroups();
1199
1200 return true;
1201 }
1202
1204};
1205
1206
1208{
1209 BOX2I r;
1210
1211 r.SetMaximum();
1212 CLEAR_LAYER_CACHE_VISITOR visitor( this );
1213
1214 for( VIEW_LAYER& layer : m_layers )
1215 layer.items->Query( r, visitor );
1216}
1217
1218
1219void VIEW::invalidateItem( VIEW_ITEM* aItem, int aUpdateFlags )
1220{
1221 if( aUpdateFlags & INITIAL_ADD )
1222 {
1223 // Don't update layers or bbox, since it was done in VIEW::Add()
1224 // Now that we have initialized, set flags to ALL for the code below
1225 aUpdateFlags = ALL;
1226 }
1227 else
1228 {
1229 // updateLayers updates geometry too, so we do not have to update both of them at the
1230 // same time
1231 if( aUpdateFlags & LAYERS )
1232 updateLayers( aItem );
1233 else if( aUpdateFlags & GEOMETRY )
1234 updateBbox( aItem );
1235 }
1236
1237 int layers[VIEW_MAX_LAYERS], layers_count;
1238 aItem->ViewGetLayers( layers, layers_count );
1239
1240 // Iterate through layers used by the item and recache it immediately
1241 for( int i = 0; i < layers_count; ++i )
1242 {
1243 int layerId = layers[i];
1244
1245 if( IsCached( layerId ) )
1246 {
1247 if( aUpdateFlags & ( GEOMETRY | LAYERS | REPAINT ) )
1248 updateItemGeometry( aItem, layerId );
1249 else if( aUpdateFlags & COLOR )
1250 updateItemColor( aItem, layerId );
1251 }
1252
1253 // Mark those layers as dirty, so the VIEW will be refreshed
1254 MarkTargetDirty( m_layers[layerId].target );
1255 }
1256
1257 aItem->viewPrivData()->clearUpdateFlags();
1258}
1259
1260
1262{
1263 int n = 0;
1264
1265 m_orderedLayers.resize( m_layers.size() );
1266
1267 for( VIEW_LAYER& layer : m_layers )
1268 m_orderedLayers[n++] = &layer;
1269
1271
1272 MarkDirty();
1273}
1274
1275
1276void VIEW::updateItemColor( VIEW_ITEM* aItem, int aLayer )
1277{
1278 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1279 wxCHECK( (unsigned) aLayer < m_layers.size(), /*void*/ );
1280 wxCHECK( IsCached( aLayer ), /*void*/ );
1281
1282 if( !viewData )
1283 return;
1284
1285 // Obtain the color that should be used for coloring the item on the specific layerId
1286 const COLOR4D color = m_painter->GetSettings()->GetColor( aItem, aLayer );
1287 int group = viewData->getGroup( aLayer );
1288
1289 // Change the color, only if it has group assigned
1290 if( group >= 0 )
1292}
1293
1294
1295void VIEW::updateItemGeometry( VIEW_ITEM* aItem, int aLayer )
1296{
1297 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1298 wxCHECK( (unsigned) aLayer < m_layers.size(), /*void*/ );
1299 wxCHECK( IsCached( aLayer ), /*void*/ );
1300
1301 if( !viewData )
1302 return;
1303
1304 VIEW_LAYER& l = m_layers.at( aLayer );
1305
1306 m_gal->SetTarget( l.target );
1308
1309 // Redraw the item from scratch
1310 int group = viewData->getGroup( aLayer );
1311
1312 if( group >= 0 )
1314
1315 group = m_gal->BeginGroup();
1316 viewData->setGroup( aLayer, group );
1317
1318 if( !m_painter->Draw( static_cast<EDA_ITEM*>( aItem ), aLayer ) )
1319 aItem->ViewDraw( aLayer, this ); // Alternative drawing method
1320
1321 m_gal->EndGroup();
1322}
1323
1324
1326{
1327 int layers[VIEW_MAX_LAYERS], layers_count;
1328
1329 aItem->ViewGetLayers( layers, layers_count );
1330
1331 for( int i = 0; i < layers_count; ++i )
1332 {
1333 VIEW_LAYER& l = m_layers[layers[i]];
1334 l.items->Remove( aItem );
1335 l.items->Insert( aItem );
1337 }
1338}
1339
1340
1342{
1343 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1344 int layers[VIEW_MAX_LAYERS], layers_count;
1345
1346 if( !viewData )
1347 return;
1348
1349 // Remove the item from previous layer set
1350 viewData->getLayers( layers, layers_count );
1351
1352 for( int i = 0; i < layers_count; ++i )
1353 {
1354 VIEW_LAYER& l = m_layers[layers[i]];
1355 l.items->Remove( aItem );
1357
1358 if( IsCached( l.id ) )
1359 {
1360 // Redraw the item from scratch
1361 int prevGroup = viewData->getGroup( layers[i] );
1362
1363 if( prevGroup >= 0 )
1364 {
1365 m_gal->DeleteGroup( prevGroup );
1366 viewData->setGroup( l.id, -1 );
1367 }
1368 }
1369 }
1370
1371 // Add the item to new layer set
1372 aItem->ViewGetLayers( layers, layers_count );
1373 viewData->saveLayers( layers, layers_count );
1374
1375 for( int i = 0; i < layers_count; i++ )
1376 {
1377 VIEW_LAYER& l = m_layers[layers[i]];
1378 l.items->Insert( aItem );
1380 }
1381}
1382
1383
1384bool VIEW::areRequiredLayersEnabled( int aLayerId ) const
1385{
1386 wxCHECK( (unsigned) aLayerId < m_layers.size(), false );
1387
1388 std::set<int>::const_iterator it, it_end;
1389
1390 for( int layer : m_layers.at( aLayerId ).requiredLayers )
1391 {
1392 // That is enough if just one layer is not enabled
1393 if( !m_layers.at( layer ).visible || !areRequiredLayersEnabled( layer ) )
1394 return false;
1395 }
1396
1397 return true;
1398}
1399
1400
1402{
1403 BOX2I r;
1404
1405 r.SetMaximum();
1406
1407 for( const VIEW_LAYER& l : m_layers )
1408 {
1409 if( IsCached( l.id ) )
1410 {
1411 RECACHE_ITEM_VISITOR visitor( this, m_gal, l.id );
1412 l.items->Query( r, visitor );
1413 }
1414 }
1415}
1416
1417
1419{
1420 if( !m_gal->IsVisible() || !m_gal->IsInitialized() )
1421 return;
1422
1423 unsigned int cntGeomUpdate = 0;
1424 bool anyUpdated = false;
1425
1426 for( VIEW_ITEM* item : *m_allItems )
1427 {
1428 auto vpd = item->viewPrivData();
1429
1430 if( !vpd )
1431 continue;
1432
1433 if( vpd->m_requiredUpdate != NONE )
1434 {
1435 anyUpdated = true;
1436
1437 if( vpd->m_requiredUpdate & ( GEOMETRY | LAYERS ) )
1438 {
1439 cntGeomUpdate++;
1440 }
1441 }
1442 }
1443
1444 unsigned int cntTotal = m_allItems->size();
1445
1446 double ratio = (double) cntGeomUpdate / (double) cntTotal;
1447
1448 // Optimization to improve view update time. If a lot of items (say, 30%) have their
1449 // bboxes/geometry changed it's way faster (around 10 times) to rebuild the R-Trees
1450 // from scratch rather than update the bbox of each changed item. Pcbnew does multiple
1451 // full geometry updates during file load, this can save a solid 30 seconds on load time
1452 // for larger designs...
1453
1454 if( ratio > 0.3 )
1455 {
1456 auto allItems = *m_allItems;
1457 int layers[VIEW_MAX_LAYERS], layers_count;
1458
1459 // kill all Rtrees
1460 for( VIEW_LAYER& layer : m_layers )
1461 layer.items->RemoveAll();
1462
1463 // and re-insert items from scratch
1464 for( VIEW_ITEM* item : allItems )
1465 {
1466 item->ViewGetLayers( layers, layers_count );
1467 item->viewPrivData()->saveLayers( layers, layers_count );
1468
1469 for( int i = 0; i < layers_count; ++i )
1470 {
1471 wxCHECK2_MSG( layers[i] >= 0 && static_cast<unsigned>( layers[i] ) < m_layers.size(),
1472 continue, wxS( "Invalid layer" ) );
1473 VIEW_LAYER& l = m_layers[layers[i]];
1474 l.items->Insert( item );
1476 }
1477
1478 item->viewPrivData()->m_requiredUpdate &= ~( LAYERS | GEOMETRY );
1479 }
1480 }
1481
1482 if( anyUpdated )
1483 {
1485
1486 for( VIEW_ITEM* item : *m_allItems.get() )
1487 {
1488 if( item->viewPrivData() && item->viewPrivData()->m_requiredUpdate != NONE )
1489 {
1490 invalidateItem( item, item->viewPrivData()->m_requiredUpdate );
1491 item->viewPrivData()->m_requiredUpdate = NONE;
1492 }
1493 }
1494 }
1495
1496 KI_TRACE( traceGalProfile, wxS( "View update: total items %u, geom %u anyUpdated %u\n" ), cntTotal,
1497 cntGeomUpdate, (unsigned) anyUpdated );
1498}
1499
1500
1501void VIEW::UpdateAllItems( int aUpdateFlags )
1502{
1503 for( VIEW_ITEM* item : *m_allItems )
1504 {
1505 if( item->viewPrivData() )
1506 item->viewPrivData()->m_requiredUpdate |= aUpdateFlags;
1507 }
1508}
1509
1510
1512 std::function<bool( VIEW_ITEM* )> aCondition )
1513{
1514 for( VIEW_ITEM* item : *m_allItems )
1515 {
1516 if( aCondition( item ) )
1517 {
1518 if( item->viewPrivData() )
1519 item->viewPrivData()->m_requiredUpdate |= aUpdateFlags;
1520 }
1521 }
1522}
1523
1524
1525void VIEW::UpdateAllItemsConditionally( std::function<int( VIEW_ITEM* )> aItemFlagsProvider )
1526{
1527 for( VIEW_ITEM* item : *m_allItems )
1528 {
1529 if( item->viewPrivData() )
1530 item->viewPrivData()->m_requiredUpdate |= aItemFlagsProvider( item );
1531 }
1532}
1533
1534
1535
1536std::unique_ptr<VIEW> VIEW::DataReference() const
1537{
1538 std::unique_ptr<VIEW> ret = std::make_unique<VIEW>();
1539 ret->m_allItems = m_allItems;
1540 ret->m_layers = m_layers;
1541 ret->sortLayers();
1542 return ret;
1543}
1544
1545
1546void VIEW::SetVisible( VIEW_ITEM* aItem, bool aIsVisible )
1547{
1548 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1549
1550 if( !viewData )
1551 return;
1552
1553 bool cur_visible = viewData->m_flags & VISIBLE;
1554
1555 if( cur_visible != aIsVisible )
1556 {
1557 if( aIsVisible )
1558 viewData->m_flags |= VISIBLE;
1559 else
1560 viewData->m_flags &= ~VISIBLE;
1561
1562 Update( aItem, APPEARANCE | COLOR );
1563 }
1564}
1565
1566
1567void VIEW::Hide( VIEW_ITEM* aItem, bool aHide )
1568{
1569 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1570
1571 if( !viewData )
1572 return;
1573
1574 if( !( viewData->m_flags & VISIBLE ) )
1575 return;
1576
1577 if( aHide )
1578 viewData->m_flags |= HIDDEN;
1579 else
1580 viewData->m_flags &= ~HIDDEN;
1581
1582 Update( aItem, APPEARANCE );
1583}
1584
1585
1586bool VIEW::IsVisible( const VIEW_ITEM* aItem ) const
1587{
1588 const VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1589
1590 return viewData && ( viewData->m_flags & VISIBLE );
1591}
1592
1593
1594bool VIEW::HasItem( const VIEW_ITEM* aItem ) const
1595{
1596 const VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1597
1598 return viewData && viewData->m_view == this;
1599}
1600
1601
1602void VIEW::Update( const VIEW_ITEM* aItem ) const
1603{
1604 Update( aItem, ALL );
1605}
1606
1607
1608void VIEW::Update( const VIEW_ITEM* aItem, int aUpdateFlags ) const
1609{
1610 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1611
1612 if( !viewData )
1613 return;
1614
1615 assert( aUpdateFlags != NONE );
1616
1617 viewData->m_requiredUpdate |= aUpdateFlags;
1618}
1619
1620
1621std::shared_ptr<VIEW_OVERLAY> VIEW::MakeOverlay()
1622{
1623 std::shared_ptr<VIEW_OVERLAY> overlay = std::make_shared<VIEW_OVERLAY>();
1624
1625 Add( overlay.get() );
1626 return overlay;
1627}
1628
1629
1631{
1632 if( !m_preview )
1633 return;
1634
1635 m_preview->Clear();
1636
1637 for( EDA_ITEM *item : m_ownedItems )
1638 delete item;
1639
1640 m_ownedItems.clear();
1641 Update( m_preview.get() );
1642}
1643
1644
1646{
1647 m_preview.reset( new KIGFX::VIEW_GROUP() );
1648 Add( m_preview.get() );
1649}
1650
1651
1652void VIEW::AddToPreview( EDA_ITEM* aItem, bool aTakeOwnership )
1653{
1654 Hide( aItem, false );
1655 m_preview->Add( aItem );
1656
1657 if( aTakeOwnership )
1658 m_ownedItems.push_back( aItem );
1659
1660 SetVisible( m_preview.get(), true );
1661 Hide( m_preview.get(), false );
1662 Update( m_preview.get() );
1663}
1664
1665
1666void VIEW::ShowPreview( bool aShow )
1667{
1668 SetVisible( m_preview.get(), aShow );
1669}
1670
1671
1672} // namespace KIGFX
int color
Definition: DXF_plotter.cpp:57
constexpr int ARC_LOW_DEF
Definition: base_units.h:120
void SetOrigin(const Vec &pos)
Definition: box2.h:203
BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:120
const Vec & GetPosition() const
Definition: box2.h:185
void SetMaximum()
Definition: box2.h:64
coord_type GetTop() const
Definition: box2.h:195
coord_type GetHeight() const
Definition: box2.h:189
coord_type GetWidth() const
Definition: box2.h:188
void SetSize(const Vec &size)
Definition: box2.h:214
bool Contains(const Vec &aPoint) const
Definition: box2.h:142
Vec Centre() const
Definition: box2.h:71
coord_type GetRight() const
Definition: box2.h:190
coord_type GetLeft() const
Definition: box2.h:194
const Vec & GetSize() const
Definition: box2.h:180
coord_type GetBottom() const
Definition: box2.h:191
void SetEnd(coord_type x, coord_type y)
Definition: box2.h:256
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:103
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 bool IsInitialized() const
Return the initialization status for the canvas.
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.
virtual void EnableDepthTest(bool aEnabled=false)
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
double m_forcedTransparency
Additional transparency for diff'ing items.
Definition: view_item.h:159
VIEW_ITEM_DATA * viewPrivData() const
Definition: view_item.h:140
virtual void ViewDraw(int aLayer, VIEW *aView) const
Draw the parts of the object belonging to layer aLayer.
Definition: view_item.h:108
virtual void ViewGetLayers(int aLayers[], int &aCount) const =0
Return the all the layers within the VIEW the object is painted on.
virtual double ViewGetLOD(int aLayer, VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition: view_item.h:134
VIEW_ITEM_DATA * m_viewPrivData
Definition: view_item.h:158
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:1666
void sortLayers()
Clear cached GAL group numbers (ONLY numbers stored in VIEW_ITEMs, not group objects used by GAL)
Definition: view.cpp:1261
double m_maxScale
Definition: view.h:858
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:841
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:730
void draw(VIEW_ITEM *aItem, int aLayer, bool aImmediate=false)
Draw an item, but on a specified layers.
Definition: view.cpp:1032
bool m_reverseDrawOrder
Definition: view.h:883
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:1276
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:819
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:314
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:351
std::vector< EDA_ITEM * > m_ownedItems
Whether to use rendering order modifier or not.
Definition: view.h:835
void ClearTargets()
Clear targets that are marked as dirty.
Definition: view.cpp:1131
virtual void EnableTopLayer(bool aEnable)
Enable or disable display of the top layer.
Definition: view.cpp:849
bool m_mirrorX
Definition: view.h:860
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:861
std::shared_ptr< std::vector< VIEW_ITEM * > > m_allItems
The set of layers that are displayed on the top.
Definition: view.h:847
std::shared_ptr< VIEW_OVERLAY > MakeOverlay()
Definition: view.cpp:1621
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:1608
void invalidateItem(VIEW_ITEM *aItem, int aUpdateFlags)
Manage dirty flags & redraw queuing when updating an item.
Definition: view.cpp:1219
const VECTOR2I & GetScreenPixelSize() const
Return the size of the our rendering area in pixels.
Definition: view.cpp:1183
bool HasItem(const VIEW_ITEM *aItem) const
Indicates whether or not the given item has been added to the view.
Definition: view.cpp:1594
virtual int GetTopLayer() const
Definition: view.cpp:813
PAINTER * m_painter
Interface to #PAINTER that is used to draw items.
Definition: view.h:864
virtual void Redraw()
Immediately redraws the whole view.
Definition: view.cpp:1150
void Clear()
Remove all items from the view.
Definition: view.cpp:1116
std::set< unsigned int > m_topLayers
Center point of the VIEW (the point at which we are looking at).
Definition: view.h:850
void AddToPreview(EDA_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1652
bool m_enableOrderModifier
The set of possible displayed layers and its properties.
Definition: view.h:838
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:1567
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:1645
void ClearPreview()
Definition: view.cpp:1630
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:1295
static constexpr int VIEW_MAX_LAYERS
Rendering order modifier for layers that are marked as top layers.
Definition: view.h:727
double m_minScale
Definition: view.h:857
double m_scale
Definition: view.h:855
void updateLayers(VIEW_ITEM *aItem)
Determine rendering order of layers. Used in display order sorting function.
Definition: view.cpp:1341
void RecacheAllItems()
Rebuild GAL display lists.
Definition: view.cpp:1401
bool areRequiredLayersEnabled(int aLayerId) const
Definition: view.cpp:1384
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:880
VIEW(bool aIsDynamic=true)
Definition: view.cpp:254
bool m_useDrawPriority
The next sequential drawing priority.
Definition: view.h:877
void UpdateItems()
Iterate through the list of items that asked for updating and updates them.
Definition: view.cpp:1418
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:1501
std::unique_ptr< KIGFX::VIEW_GROUP > m_preview
Definition: view.h:834
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:308
GAL * m_gal
Dynamic VIEW (eg.
Definition: view.h:867
std::unique_ptr< VIEW > DataReference() const
Return a new VIEW object that shares the same set of VIEW_ITEMs and LAYERs.
Definition: view.cpp:1536
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:856
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:844
void clearGroupCache()
Definition: view.cpp:1207
VECTOR2D m_center
Definition: view.h:853
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:1325
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition: view.cpp:1586
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:1511
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1546
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:989
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
Definition: matrix3x3.h:295
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 difference For aFastMode meaning, see function booleanOp.
@ ALLOW_ACUTE_CORNERS
just inflate the polygon. Acute angles create spikes
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
void Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
#define _(s)
const wxChar *const traceGalProfile
Flag to enable debug output of GAL performance profiling.
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:247
@ 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:1196
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:933
DRAW_ITEM_VISITOR(VIEW *aView, int aLayer, bool aUseDrawPriority, bool aReverseDrawOrder)
Definition: view.cpp:923
int layers[VIEW_MAX_LAYERS]
Definition: view.cpp:981
std::vector< VIEW_ITEM * > drawItems
Definition: view.cpp:983
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:1091
RECACHE_ITEM_VISITOR(VIEW *aView, GAL *aGal, int aLayer)
Definition: view.cpp:1084
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:740
std::shared_ptr< VIEW_RTREE > items
R-tree indexing all items on this layer.
Definition: view.h:739
RENDER_TARGET target
Where the layer should be rendered.
Definition: view.h:742
int id
Layer ID.
Definition: view.h:741
constexpr int delta
wxLogTrace helper definitions.
#define KI_TRACE(aWhat,...)
VECTOR2< double > VECTOR2D
Definition: vector2d.h:587