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 The 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 <layer_ids.h>
30#include <trace_helpers.h>
31
32#include <view/view.h>
33#include <view/view_group.h>
34#include <view/view_item.h>
35#include <view/view_rtree.h>
36#include <view/view_overlay.h>
37
38#include <gal/definitions.h>
40#include <gal/painter.h>
41#include <algorithm>
42
43#include <core/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_cachedIndex( -1 ),
62 m_groups( nullptr ),
63 m_groupsSize( 0 ) {}
64
66 {
68 }
69
70 int GetFlags() const
71 {
72 return m_flags;
73 }
74
75private:
76 friend class VIEW;
77
84 int getGroup( int aLayer ) const
85 {
86 for( int i = 0; i < m_groupsSize; ++i )
87 {
88 if( m_groups[i].first == aLayer )
89 return m_groups[i].second;
90 }
91
92 return -1;
93 }
94
101 void setGroup( int aLayer, int aGroup )
102 {
103 // Look if there is already an entry for the layer
104 for( int i = 0; i < m_groupsSize; ++i )
105 {
106 if( m_groups[i].first == aLayer )
107 {
108 m_groups[i].second = aGroup;
109 return;
110 }
111 }
112
113 // If there was no entry for the given layer - create one
114 std::pair<int, int>* newGroups = new std::pair<int, int>[m_groupsSize + 1];
115
116 if( m_groupsSize > 0 )
117 {
118 std::copy( m_groups, m_groups + m_groupsSize, newGroups );
119 delete[] m_groups;
120 }
121
122 m_groups = newGroups;
123 newGroups[m_groupsSize++] = { aLayer, aGroup };
124 }
125
126
131 {
132 delete[] m_groups;
133 m_groups = nullptr;
134 m_groupsSize = 0;
135 }
136
142 inline bool storesGroups() const
143 {
144 return m_groupsSize > 0;
145 }
146
154 void reorderGroups( std::unordered_map<int, int> aReorderMap )
155 {
156 for( int i = 0; i < m_groupsSize; ++i )
157 {
158 int orig_layer = m_groups[i].first;
159 int new_layer = orig_layer;
160
161 if( aReorderMap.count( orig_layer ) )
162 new_layer = aReorderMap.at( orig_layer );
163
164 m_groups[i].first = new_layer;
165 }
166 }
167
174 void saveLayers( const std::vector<int>& aLayers )
175 {
176 m_layers.clear();
177
178 for( int layer : aLayers )
179 {
180 wxCHECK2_MSG( layer >= 0 && layer < VIEW::VIEW_MAX_LAYERS, continue,
181 wxString::Format( wxT( "Invalid layer number: %d" ), layer ) );
182 m_layers.push_back( layer );
183 }
184 }
185
189 int requiredUpdate() const
190 {
191 return m_requiredUpdate;
192 }
193
198 {
200 }
201
205 bool isRenderable() const
206 {
207 return m_flags == VISIBLE;
208 }
209
215
216 std::pair<int, int>* m_groups;
219
220 std::vector<int> m_layers;
221
223};
224
225
227{
228 if( aItem->m_viewPrivData )
229 {
230 if( aItem->m_viewPrivData->m_view )
231 aItem->m_viewPrivData->m_view->VIEW::Remove( aItem );
232
233 delete aItem->m_viewPrivData;
234 aItem->m_viewPrivData = nullptr;
235 }
236}
237
238
240 m_enableOrderModifier( true ),
241 m_scale( 4.0 ),
242 m_minScale( 0.2 ), m_maxScale( 50000.0 ),
243 m_mirrorX( false ), m_mirrorY( false ),
244 m_painter( nullptr ),
245 m_gal( nullptr ),
246 m_useDrawPriority( false ),
247 m_nextDrawPriority( 0 ),
248 m_reverseDrawOrder( false )
249{
250 // Set m_boundary to define the max area size. The default area size
251 // is defined here as the max value of a int.
252 // this is a default value acceptable for Pcbnew and Gerbview, but too large for Eeschema.
253 // So in eeschema a call to SetBoundary() with a smaller value will be needed.
254 typedef std::numeric_limits<int> coord_limits;
255 double pos = coord_limits::lowest() / 2 + coord_limits::epsilon();
256 double size = coord_limits::max() - coord_limits::epsilon();
257 m_boundary.SetOrigin( pos, pos );
258 m_boundary.SetSize( size, size );
259
260 m_allItems.reset( new std::vector<VIEW_ITEM*> );
261 m_allItems->reserve( 32768 );
262
263 // Redraw everything at the beginning
264 MarkDirty();
265
266 // View uses layers to display EDA_ITEMs (item may be displayed on several layers, for example
267 // pad may be shown on pad, pad hole and solder paste layers). There are usual copper layers
268 // (eg. F.Cu, B.Cu, internal and so on) and layers for displaying objects such as texts,
269 // silkscreen, pads, vias, etc.
270 for( int ii = 0; ii < VIEW_MAX_LAYERS; ++ii )
271 {
272 auto [it, _] = m_layers.emplace( ii, VIEW_LAYER() );
273 VIEW_LAYER& l = it->second;
274
275 l.items = std::make_shared<VIEW_RTREE>();
276 l.id = ii;
277 l.renderingOrder = ii;
278 l.visible = true;
279 l.displayOnly = false;
280 l.diffLayer = false;
281 l.hasNegatives = false;
283 }
284
286
287 m_preview.reset( new KIGFX::VIEW_GROUP() );
288 Add( m_preview.get() );
289}
290
291
293{
294 Remove( m_preview.get() );
295}
296
297
298void VIEW::Add( VIEW_ITEM* aItem, int aDrawPriority )
299{
300 if( aDrawPriority < 0 )
301 aDrawPriority = m_nextDrawPriority++;
302
303 if( !aItem->m_viewPrivData )
304 aItem->m_viewPrivData = new VIEW_ITEM_DATA;
305
306 wxASSERT_MSG( aItem->m_viewPrivData->m_view == nullptr || aItem->m_viewPrivData->m_view == this,
307 wxS( "Already in a different view!" ) );
308
309 aItem->m_viewPrivData->m_view = this;
310 aItem->m_viewPrivData->m_drawPriority = aDrawPriority;
311 const BOX2I bbox = aItem->ViewBBox();
312 aItem->m_viewPrivData->m_bbox = bbox;
313 aItem->m_viewPrivData->m_cachedIndex = m_allItems->size();
314
315 std::vector<int> layers = aItem->ViewGetLayers();
316
317 std::erase_if( layers, []( int layer )
318 {
319 return layer < 0 || layer >= VIEW_MAX_LAYERS;
320 } );
321
322 if( layers.empty() )
323 return;
324
325 aItem->viewPrivData()->saveLayers( layers );
326
327 m_allItems->push_back( aItem );
328
329 for( int layer : layers )
330 {
331 VIEW_LAYER& l = m_layers[layer];
332 l.items->Insert( aItem, bbox );
334 }
335
336 SetVisible( aItem, true );
337 Update( aItem, KIGFX::INITIAL_ADD );
338}
339
340
342{
343 static int s_gcCounter = 0;
344
345 if( aItem && aItem->m_viewPrivData )
346 {
347 wxCHECK_MSG( aItem->m_viewPrivData->m_view == this, /*void*/, aItem->GetClass() );
348
349 std::vector<VIEW_ITEM*>::iterator item = m_allItems->end();
350 int cachedIndex = aItem->m_viewPrivData->m_cachedIndex;
351
352 if( cachedIndex >= 0
353 && cachedIndex < static_cast<ssize_t>( m_allItems->size() )
354 && ( *m_allItems )[cachedIndex] == aItem )
355 {
356 item = m_allItems->begin() + cachedIndex;
357 }
358 else
359 {
360 item = std::find( m_allItems->begin(), m_allItems->end(), aItem );
361 }
362
363 if( item != m_allItems->end() )
364 {
365 *item = nullptr;
367
368 s_gcCounter++;
369
370 if( s_gcCounter > 4096 )
371 {
372 // Perform defragmentation
373 std::erase_if( *m_allItems,
374 []( VIEW_ITEM* it )
375 {
376 return it == nullptr;
377 } );
378
379 // Update cached indices
380 for( size_t idx = 0; idx < m_allItems->size(); idx++ )
381 ( *m_allItems )[idx]->m_viewPrivData->m_cachedIndex = idx;
382
383 s_gcCounter = 0;
384 }
385 }
386
387 const BOX2I* bbox = &aItem->m_viewPrivData->m_bbox;
388
389 for( int layer : aItem->m_viewPrivData->m_layers )
390 {
391 VIEW_LAYER& l = m_layers[layer];
392 l.items->Remove( aItem, bbox );
394
395 // Clear the GAL cache
396 int prevGroup = aItem->m_viewPrivData->getGroup( layer );
397
398 if( prevGroup >= 0 )
399 m_gal->DeleteGroup( prevGroup );
400 }
401
403 aItem->m_viewPrivData->m_view = nullptr;
404 }
405}
406
407
408void VIEW::SetRequired( int aLayerId, int aRequiredId, bool aRequired )
409{
410 wxCHECK( (unsigned) aLayerId < m_layers.size(), /*void*/ );
411 wxCHECK( (unsigned) aRequiredId < m_layers.size(), /*void*/ );
412
413 if( aRequired )
414 m_layers[aLayerId].requiredLayers.insert( aRequiredId );
415 else
416 m_layers[aLayerId].requiredLayers.erase( aRequired );
417}
418
419
420int VIEW::Query( const BOX2I& aRect, std::vector<LAYER_ITEM_PAIR>& aResult ) const
421{
422 if( m_orderedLayers.empty() )
423 return 0;
424
425 int layer = UNDEFINED_LAYER;
426 auto visitor =
427 [&]( VIEW_ITEM* item ) -> bool
428 {
429 aResult.push_back( VIEW::LAYER_ITEM_PAIR( item, layer ) );
430 return true;
431 };
432
433 std::vector<VIEW_LAYER*>::const_reverse_iterator i;
434
435 // execute queries in reverse direction, so that items that are on the top of
436 // the rendering stack are returned first.
437 for( i = m_orderedLayers.rbegin(); i != m_orderedLayers.rend(); ++i )
438 {
439 // ignore layers that do not contain actual items (i.e. the selection box, menus, floats)
440 if( ( *i )->displayOnly || !( *i )->visible )
441 continue;
442
443 layer = ( *i )->id;
444 ( *i )->items->Query( aRect, visitor );
445 }
446
447 return aResult.size();
448}
449
450
451void VIEW::Query( const BOX2I& aRect, const std::function<bool( VIEW_ITEM* )>& aFunc ) const
452{
453 if( m_orderedLayers.empty() )
454 return;
455
456 for( const auto& i : m_orderedLayers )
457 {
458 // ignore layers that do not contain actual items (i.e. the selection box, menus, floats)
459 if( i->displayOnly || !i->visible )
460 continue;
461
462 i->items->Query( aRect, aFunc );
463 }
464}
465
466
467VECTOR2D VIEW::ToWorld( const VECTOR2D& aCoord, bool aAbsolute ) const
468{
469 const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
470
471 if( aAbsolute )
472 return VECTOR2D( matrix * aCoord );
473 else
474 return VECTOR2D( matrix.GetScale().x * aCoord.x, matrix.GetScale().y * aCoord.y );
475}
476
477
478double VIEW::ToWorld( double aSize ) const
479{
480 const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
481
482 return fabs( matrix.GetScale().x * aSize );
483}
484
485
486VECTOR2D VIEW::ToScreen( const VECTOR2D& aCoord, bool aAbsolute ) const
487{
488 const MATRIX3x3D& matrix = m_gal->GetWorldScreenMatrix();
489
490 if( aAbsolute )
491 return VECTOR2D( matrix * aCoord );
492 else
493 return VECTOR2D( matrix.GetScale().x * aCoord.x, matrix.GetScale().y * aCoord.y );
494}
495
496
497double VIEW::ToScreen( double aSize ) const
498{
499 const MATRIX3x3D& matrix = m_gal->GetWorldScreenMatrix();
500
501 return matrix.GetScale().x * aSize;
502}
503
504
505void VIEW::CopySettings( const VIEW* aOtherView )
506{
507 wxASSERT_MSG( false, wxT( "This is not implemented" ) );
508}
509
510
511void VIEW::SetGAL( GAL* aGal )
512{
513 bool recacheGroups = ( m_gal != nullptr ); // recache groups only if GAL is reassigned
514 m_gal = aGal;
515
516 // clear group numbers, so everything is going to be recached
517 if( recacheGroups )
519
520 // every target has to be refreshed
521 MarkDirty();
522
523 // force the new GAL to display the current viewport.
525 SetScale( m_scale );
527}
528
529
531{
532 BOX2D rect;
533 VECTOR2D screenSize = m_gal->GetScreenPixelSize();
534
535 rect.SetOrigin( ToWorld( VECTOR2D( 0, 0 ) ) );
536 rect.SetEnd( ToWorld( screenSize ) );
537
538 return rect.Normalize();
539}
540
541
542void VIEW::SetViewport( const BOX2D& aViewport )
543{
544 VECTOR2D ssize = ToWorld( m_gal->GetScreenPixelSize(), false );
545
546 wxCHECK( fabs(ssize.x) > 0 && fabs(ssize.y) > 0, /*void*/ );
547
548 VECTOR2D centre = aViewport.Centre();
549 VECTOR2D vsize = aViewport.GetSize();
550 double zoom = 1.0 / std::max( fabs( vsize.x / ssize.x ), fabs( vsize.y / ssize.y ) );
551
552 SetCenter( centre );
553 SetScale( GetScale() * zoom );
554}
555
556
557void VIEW::SetMirror( bool aMirrorX, bool aMirrorY )
558{
559 wxASSERT_MSG( !aMirrorY, _( "Mirroring for Y axis is not supported yet" ) );
560
561 m_mirrorX = aMirrorX;
562 m_mirrorY = aMirrorY;
563 m_gal->SetFlip( aMirrorX, aMirrorY );
564
565 // Redraw everything
566 MarkDirty();
567}
568
569
570void VIEW::SetScale( double aScale, VECTOR2D aAnchor )
571{
572 if( aAnchor == VECTOR2D( 0, 0 ) )
573 aAnchor = m_center;
574
575 VECTOR2D a = ToScreen( aAnchor );
576
577 if( aScale < m_minScale )
579 else if( aScale > m_maxScale )
581 else
582 m_scale = aScale;
583
586
587 VECTOR2D delta = ToWorld( a ) - aAnchor;
588
590
591 // Redraw everything after the viewport has changed
592 MarkDirty();
593}
594
595
596void VIEW::SetCenter( const VECTOR2D& aCenter )
597{
598 m_center = aCenter;
599
600 if( !m_boundary.Contains( aCenter ) )
601 {
602 if( m_center.x < m_boundary.GetLeft() )
604 else if( aCenter.x > m_boundary.GetRight() )
606
607 if( m_center.y < m_boundary.GetTop() )
609 else if( m_center.y > m_boundary.GetBottom() )
611 }
612
615
616 // Redraw everything after the viewport has changed
617 MarkDirty();
618}
619
620
621void VIEW::SetCenter( const VECTOR2D& aCenter, const std::vector<BOX2D>& obscuringScreenRects )
622{
623 if( obscuringScreenRects.empty() )
624 return SetCenter( aCenter );
625
626 BOX2D screenRect( { 0, 0 }, m_gal->GetScreenPixelSize() );
627 SHAPE_POLY_SET unobscuredPoly( screenRect );
628 VECTOR2D unobscuredCenter = screenRect.Centre();
629
630 for( const BOX2D& obscuringScreenRect : obscuringScreenRects )
631 {
632 SHAPE_POLY_SET obscuringPoly( obscuringScreenRect );
633 unobscuredPoly.BooleanSubtract( obscuringPoly );
634 }
635
636 /*
637 * Perform a step-wise deflate to find the center of the largest unobscured area
638 */
639
640 BOX2I bbox = unobscuredPoly.BBox();
641 int step = std::min( bbox.GetWidth(), bbox.GetHeight() ) / 10;
642
643 if( step < 20 )
644 step = 20;
645
646 while( !unobscuredPoly.IsEmpty() )
647 {
648 unobscuredCenter = unobscuredPoly.BBox().Centre();
649 unobscuredPoly.Deflate( step, CORNER_STRATEGY::ALLOW_ACUTE_CORNERS, ARC_LOW_DEF );
650 }
651
652 SetCenter( aCenter - ToWorld( unobscuredCenter - screenRect.Centre(), false ) );
653}
654
655
656void VIEW::SetLayerOrder( int aLayer, int aRenderingOrder )
657{
658 m_layers[aLayer].renderingOrder = aRenderingOrder;
659
661}
662
663
664int VIEW::GetLayerOrder( int aLayer ) const
665{
666 return m_layers.at( aLayer ).renderingOrder;
667}
668
669
670void VIEW::SortLayers( std::vector<int>& aLayers ) const
671{
672 std::sort( aLayers.begin(), aLayers.end(),
673 [this]( int a, int b )
674 {
675 return GetLayerOrder( a ) > GetLayerOrder( b );
676 } );
677}
678
679
680void VIEW::ReorderLayerData( std::unordered_map<int, int> aReorderMap )
681{
682 std::map<int,VIEW_LAYER> new_map;
683
684 for( auto& [_, layer] : m_layers )
685 {
686 auto reorder_it = aReorderMap.find( layer.id );
687
688 // If the layer is not in the reorder map or if it is mapped to itself,
689 // just copy the layer to the new map.
690 if( reorder_it == aReorderMap.end() || reorder_it->second == layer.id )
691 {
692 new_map.emplace( layer.id, layer );
693 continue;
694 }
695
696 auto [new_it,__] = new_map.emplace( reorder_it->second, layer );
697 new_it->second.id = reorder_it->second;
698 }
699
700 // Transfer reordered data (using the copy assignment operator ):
701 m_layers = new_map;
702
704
705 for( VIEW_ITEM* item : *m_allItems )
706 {
707 if( !item )
708 continue;
709
710 VIEW_ITEM_DATA* viewData = item->viewPrivData();
711
712 if( !viewData )
713 continue;
714
715 std::vector<int> layers = item->ViewGetLayers();
716 viewData->saveLayers( layers );
717
718 viewData->reorderGroups( aReorderMap );
719
720 viewData->m_requiredUpdate |= COLOR;
721 }
722
723 UpdateItems();
724}
725
726
728{
729 UPDATE_COLOR_VISITOR( int aLayer, PAINTER* aPainter, GAL* aGal ) :
730 layer( aLayer ),
731 painter( aPainter ),
732 gal( aGal )
733 {
734 }
735
736 bool operator()( VIEW_ITEM* aItem )
737 {
738 // Obtain the color that should be used for coloring the item
739 const COLOR4D color = painter->GetSettings()->GetColor( aItem, layer );
740 int group = aItem->viewPrivData()->getGroup( layer );
741
742 if( group >= 0 )
744
745 return true;
746 }
747
748 int layer;
751};
752
753
754void VIEW::UpdateLayerColor( int aLayer )
755{
756 // There is no point in updating non-cached layers
757 if( !IsCached( aLayer ) )
758 return;
759
760 BOX2I r;
761
762 r.SetMaximum();
763
764 if( m_gal->IsVisible() )
765 {
767
768 UPDATE_COLOR_VISITOR visitor( aLayer, m_painter, m_gal );
769 m_layers[aLayer].items->Query( r, visitor );
770 MarkTargetDirty( m_layers[aLayer].target );
771 }
772}
773
774
776{
777 if( m_gal->IsVisible() )
778 {
780
781 for( VIEW_ITEM* item : *m_allItems )
782 {
783 if( !item )
784 continue;
785
786 VIEW_ITEM_DATA* viewData = item->viewPrivData();
787
788 if( !viewData )
789 continue;
790
791 for( int layer : viewData->m_layers )
792 {
793 const COLOR4D color = m_painter->GetSettings()->GetColor( item, layer );
794 int group = viewData->getGroup( layer );
795
796 if( group >= 0 )
798 }
799 }
800 }
801
802 MarkDirty();
803}
804
805
807{
808 UPDATE_DEPTH_VISITOR( int aLayer, int aDepth, GAL* aGal ) :
809 layer( aLayer ),
810 depth( aDepth ),
811 gal( aGal )
812 {
813 }
814
815 bool operator()( VIEW_ITEM* aItem )
816 {
817 int group = aItem->viewPrivData()->getGroup( layer );
818
819 if( group >= 0 )
821
822 return true;
823 }
824
827};
828
829
831{
832 if( m_topLayers.size() == 0 )
833 return 0;
834
835 return *m_topLayers.begin();
836}
837
838
839void VIEW::SetTopLayer( int aLayer, bool aEnabled )
840{
841 if( aEnabled )
842 {
843 if( m_topLayers.count( aLayer ) == 1 )
844 return;
845
846 m_topLayers.insert( aLayer );
847
848 // Move the layer closer to front
850 m_layers[aLayer].renderingOrder += TOP_LAYER_MODIFIER;
851 }
852 else
853 {
854 if( m_topLayers.count( aLayer ) == 0 )
855 return;
856
857 m_topLayers.erase( aLayer );
858
859 // Restore the previous rendering order
861 m_layers[aLayer].renderingOrder -= TOP_LAYER_MODIFIER;
862 }
863}
864
865
866void VIEW::EnableTopLayer( bool aEnable )
867{
868 if( aEnable == m_enableOrderModifier )
869 return;
870
871 m_enableOrderModifier = aEnable;
872
873 std::set<unsigned int>::iterator it;
874
875 if( aEnable )
876 {
877 for( it = m_topLayers.begin(); it != m_topLayers.end(); ++it )
878 m_layers[*it].renderingOrder += TOP_LAYER_MODIFIER;
879 }
880 else
881 {
882 for( it = m_topLayers.begin(); it != m_topLayers.end(); ++it )
883 m_layers[*it].renderingOrder -= TOP_LAYER_MODIFIER;
884 }
885
888}
889
890
892{
893 std::set<unsigned int>::iterator it;
894
896 {
897 // Restore the previous rendering order for layers that were marked as top
898 for( it = m_topLayers.begin(); it != m_topLayers.end(); ++it )
899 m_layers[*it].renderingOrder -= TOP_LAYER_MODIFIER;
900 }
901
902 m_topLayers.clear();
903}
904
905
907{
909
910 if( m_gal->IsVisible() )
911 {
913
914 for( VIEW_ITEM* item : *m_allItems )
915 {
916 if( !item )
917 continue;
918
919 VIEW_ITEM_DATA* viewData = item->viewPrivData();
920
921 if( !viewData )
922 continue;
923
924 for( int layer : viewData->m_layers )
925 {
926 int group = viewData->getGroup( layer );
927
928 if( group >= 0 )
929 m_gal->ChangeGroupDepth( group, m_layers[layer].renderingOrder );
930 }
931 }
932 }
933
934 MarkDirty();
935}
936
937
939{
940 DRAW_ITEM_VISITOR( VIEW* aView, int aLayer, bool aUseDrawPriority, bool aReverseDrawOrder ) :
941 view( aView ),
942 layer( aLayer ),
943 useDrawPriority( aUseDrawPriority ),
944 reverseDrawOrder( aReverseDrawOrder ),
945 drawForcedTransparent( false ),
947 {
948 }
949
950 bool operator()( VIEW_ITEM* aItem )
951 {
952 wxCHECK( aItem->viewPrivData(), false );
953
955 {
957 return true;
958 }
959
960 const double itemLOD = aItem->ViewGetLOD( layer, view );
961
962 // Conditions that have to be fulfilled for an item to be drawn
963 bool drawCondition = aItem->viewPrivData()->isRenderable() && itemLOD < view->m_scale;
964
965 if( !drawCondition )
966 return true;
967
968 if( useDrawPriority )
969 drawItems.push_back( aItem );
970 else
971 view->draw( aItem, layer );
972
973 return true;
974 }
975
977 {
978 if( reverseDrawOrder )
979 {
980 std::sort( drawItems.begin(), drawItems.end(),
981 []( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool
982 {
983 return b->viewPrivData()->m_drawPriority
984 < a->viewPrivData()->m_drawPriority;
985 } );
986 }
987 else
988 {
989 std::sort( drawItems.begin(), drawItems.end(),
990 []( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool
991 {
992 return a->viewPrivData()->m_drawPriority
993 < b->viewPrivData()->m_drawPriority;
994 } );
995 }
996
997 for( VIEW_ITEM* item : drawItems )
998 view->draw( item, layer );
999 }
1000
1004 std::vector<VIEW_ITEM*> drawItems;
1007};
1008
1009
1010void VIEW::redrawRect( const BOX2I& aRect )
1011{
1012 for( VIEW_LAYER* l : m_orderedLayers )
1013 {
1014 if( l->visible && IsTargetDirty( l->target ) && areRequiredLayersEnabled( l->id ) )
1015 {
1016 DRAW_ITEM_VISITOR drawFunc( this, l->id, m_useDrawPriority, m_reverseDrawOrder );
1017
1018 m_gal->SetTarget( l->target );
1019 m_gal->SetLayerDepth( l->renderingOrder );
1020
1021 // Differential layer also work for the negatives, since both special layer types
1022 // will composite on separate layers (at least in Cairo)
1023 if( l->diffLayer )
1025 else if( l->hasNegatives )
1027
1028 l->items->Query( aRect, drawFunc );
1029
1030 if( m_useDrawPriority )
1031 drawFunc.deferredDraw();
1032
1033 if( l->diffLayer )
1035 else if( l->hasNegatives )
1037
1038 if( drawFunc.foundForcedTransparent )
1039 {
1040 drawFunc.drawForcedTransparent = true;
1041
1043 m_gal->EnableDepthTest( true );
1044 m_gal->SetLayerDepth( l->renderingOrder );
1045
1046 l->items->Query( aRect, drawFunc );
1047 }
1048 }
1049 }
1050}
1051
1052
1053void VIEW::draw( VIEW_ITEM* aItem, int aLayer, bool aImmediate )
1054{
1055 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1056
1057 if( !viewData )
1058 return;
1059
1060 if( IsCached( aLayer ) && !aImmediate )
1061 {
1062 // Draw using cached information or create one
1063 int group = viewData->getGroup( aLayer );
1064
1065 if( group >= 0 )
1066 m_gal->DrawGroup( group );
1067 else
1068 Update( aItem );
1069 }
1070 else
1071 {
1072 // Immediate mode
1073 if( !m_painter->Draw( aItem, aLayer ) )
1074 aItem->ViewDraw( aLayer, this ); // Alternative drawing method
1075 }
1076}
1077
1078
1079void VIEW::draw( VIEW_ITEM* aItem, bool aImmediate )
1080{
1081 std::vector<int> layers = aItem->ViewGetLayers();
1082
1083 // Sorting is needed for drawing order dependent GALs (like Cairo)
1084 if( !m_gal || !m_gal->IsOpenGlEngine())
1085 SortLayers( layers );
1086
1087 for( int layer : layers )
1088 {
1089 auto it = m_layers.find( layer );
1090
1091 if( it == m_layers.end() )
1092 continue;
1093
1094 if( m_gal )
1095 m_gal->SetLayerDepth( it->second.renderingOrder );
1096
1097 draw( aItem, layer, aImmediate );
1098 }
1099}
1100
1101
1102void VIEW::draw( VIEW_GROUP* aGroup, bool aImmediate )
1103{
1104 for( unsigned int i = 0; i < aGroup->GetSize(); i++ )
1105 draw( aGroup->GetItem(i), aImmediate );
1106}
1107
1108
1110{
1111 RECACHE_ITEM_VISITOR( VIEW* aView, GAL* aGal, int aLayer ) :
1112 view( aView ),
1113 gal( aGal ),
1114 layer( aLayer )
1115 {
1116 }
1117
1118 bool operator()( VIEW_ITEM* aItem )
1119 {
1120 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1121
1122 if( !viewData )
1123 return false;
1124
1125 // Remove previously cached group
1126 int group = viewData->getGroup( layer );
1127
1128 if( group >= 0 )
1129 gal->DeleteGroup( group );
1130
1131 viewData->setGroup( layer, -1 );
1132 view->Update( aItem );
1133
1134 return true;
1135 }
1136
1140};
1141
1142
1144{
1145 BOX2I r;
1146 r.SetMaximum();
1147 m_allItems->clear();
1148
1149 for( auto& [_, layer] : m_layers )
1150 layer.items->RemoveAll();
1151
1153
1154 m_gal->ClearCache();
1155}
1156
1157
1159{
1161 {
1162 // TARGET_CACHED and TARGET_NONCACHED have to be redrawn together, as they contain
1163 // layers that rely on each other (eg. netnames are noncached, but tracks - are cached)
1166
1167 MarkDirty();
1168 }
1169
1171 {
1173 }
1174}
1175
1176
1178{
1179#ifdef KICAD_GAL_PROFILE
1180 PROF_TIMER totalRealTime;
1181#endif /* KICAD_GAL_PROFILE */
1182
1183 VECTOR2D screenSize = m_gal->GetScreenPixelSize();
1184 BOX2D rect( ToWorld( VECTOR2D( 0, 0 ) ),
1185 ToWorld( screenSize ) - ToWorld( VECTOR2D( 0, 0 ) ) );
1186
1187 rect.Normalize();
1188 BOX2I recti = BOX2ISafe( rect );
1189
1190 redrawRect( recti );
1191
1192 // All targets were redrawn, so nothing is dirty
1193 MarkClean();
1194
1195#ifdef KICAD_GAL_PROFILE
1196 totalRealTime.Stop();
1197 wxLogTrace( traceGalProfile, wxS( "VIEW::Redraw(): %.1f ms" ), totalRealTime.msecs() );
1198#endif /* KICAD_GAL_PROFILE */
1199}
1200
1201
1203{
1204 return m_gal->GetScreenPixelSize();
1205}
1206
1207
1209{
1211 view( aView )
1212 {
1213 }
1214
1215 bool operator()( VIEW_ITEM* aItem )
1216 {
1217 aItem->viewPrivData()->deleteGroups();
1218
1219 return true;
1220 }
1221
1223};
1224
1225
1227{
1228 BOX2I r;
1229
1230 r.SetMaximum();
1231 CLEAR_LAYER_CACHE_VISITOR visitor( this );
1232
1233 for( auto& [_, layer] : m_layers )
1234 layer.items->Query( r, visitor );
1235}
1236
1237
1238void VIEW::invalidateItem( VIEW_ITEM* aItem, int aUpdateFlags )
1239{
1240 if( aUpdateFlags & INITIAL_ADD )
1241 {
1242 // Don't update layers or bbox, since it was done in VIEW::Add()
1243 // Now that we have initialized, set flags to ALL for the code below
1244 aUpdateFlags = ALL;
1245 }
1246 else
1247 {
1248 // updateLayers updates geometry too, so we do not have to update both of them at the
1249 // same time
1250 if( aUpdateFlags & LAYERS )
1251 updateLayers( aItem );
1252 else if( aUpdateFlags & GEOMETRY )
1253 updateBbox( aItem );
1254 }
1255
1256 std::vector<int> layers = aItem->ViewGetLayers();
1257
1258 // Iterate through layers used by the item and recache it immediately
1259 for( int layer : layers )
1260 {
1261 if( IsCached( layer ) )
1262 {
1263 if( aUpdateFlags & ( GEOMETRY | LAYERS | REPAINT ) )
1264 updateItemGeometry( aItem, layer );
1265 else if( aUpdateFlags & COLOR )
1266 updateItemColor( aItem, layer );
1267 }
1268
1269 // Mark those layers as dirty, so the VIEW will be refreshed
1270 MarkTargetDirty( m_layers[layer].target );
1271 }
1272
1273 aItem->viewPrivData()->clearUpdateFlags();
1274}
1275
1276
1278{
1279 int n = 0;
1280
1281 m_orderedLayers.resize( m_layers.size() );
1282
1283 for( auto& [layer_id, layer] : m_layers )
1284 m_orderedLayers[n++] = &layer;
1285
1287
1288 MarkDirty();
1289}
1290
1291
1292void VIEW::updateItemColor( VIEW_ITEM* aItem, int aLayer )
1293{
1294 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1295 wxCHECK( IsCached( aLayer ), /*void*/ ); // This will check if the layer exists
1296
1297 if( !viewData )
1298 return;
1299
1300 // Obtain the color that should be used for coloring the item on the specific layerId
1301 const COLOR4D color = m_painter->GetSettings()->GetColor( aItem, aLayer );
1302 int group = viewData->getGroup( aLayer );
1303
1304 // Change the color, only if it has group assigned
1305 if( group >= 0 )
1307}
1308
1309
1310void VIEW::updateItemGeometry( VIEW_ITEM* aItem, int aLayer )
1311{
1312 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1313
1314 if( !viewData )
1315 return;
1316
1317 auto it = m_layers.find( aLayer );
1318
1319 if( it == m_layers.end() )
1320 return;
1321
1322 VIEW_LAYER& l = it->second;
1323
1324 // Save the extra map lookup in IsCached by open coding here
1325 if( l.target != TARGET_CACHED )
1326 return;
1327
1328 m_gal->SetTarget( l.target );
1330
1331 // Redraw the item from scratch
1332 int group = viewData->getGroup( aLayer );
1333
1334 if( group >= 0 )
1336
1337 group = m_gal->BeginGroup();
1338 viewData->setGroup( aLayer, group );
1339
1340 if( !m_painter->Draw( aItem, aLayer ) )
1341 aItem->ViewDraw( aLayer, this ); // Alternative drawing method
1342
1343 m_gal->EndGroup();
1344}
1345
1346
1348{
1349 std::vector<int> layers = aItem->ViewGetLayers();
1350
1351 wxASSERT( aItem->m_viewPrivData ); //must have a viewPrivData
1352
1353 const BOX2I new_bbox = aItem->ViewBBox();
1354 const BOX2I* old_bbox = &aItem->m_viewPrivData->m_bbox;
1355 aItem->m_viewPrivData->m_bbox = new_bbox;
1356
1357 for( int layer : layers )
1358 {
1359 auto it = m_layers.find( layer );
1360
1361 if( it == m_layers.end() )
1362 continue;
1363
1364 VIEW_LAYER& l = it->second;
1365 l.items->Remove( aItem, old_bbox );
1366 l.items->Insert( aItem, new_bbox );
1368 }
1369}
1370
1371
1373{
1374 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1375
1376 if( !viewData )
1377 return;
1378
1379 // Remove the item from previous layer set
1380 const BOX2I* old_bbox = &aItem->m_viewPrivData->m_bbox;
1381
1382 for( int layer : aItem->m_viewPrivData->m_layers )
1383 {
1384 auto it = m_layers.find( layer );
1385
1386 if( it == m_layers.end() )
1387 continue;
1388
1389 VIEW_LAYER& l = it->second;
1390 l.items->Remove( aItem, old_bbox );
1392
1393 if( IsCached( l.id ) )
1394 {
1395 // Redraw the item from scratch
1396 int prevGroup = viewData->getGroup( layer );
1397
1398 if( prevGroup >= 0 )
1399 {
1400 m_gal->DeleteGroup( prevGroup );
1401 viewData->setGroup( l.id, -1 );
1402 }
1403 }
1404 }
1405
1406 const BOX2I new_bbox = aItem->ViewBBox();
1407 aItem->m_viewPrivData->m_bbox = new_bbox;
1408
1409 // Add the item to new layer set
1410 std::vector<int> layers = aItem->ViewGetLayers();
1411 viewData->saveLayers( layers );
1412
1413 for( int layer : layers )
1414 {
1415 auto it = m_layers.find( layer );
1416
1417 if( it == m_layers.end() )
1418 continue;
1419
1420 VIEW_LAYER& l = it->second;
1421 l.items->Insert( aItem, new_bbox );
1423 }
1424}
1425
1426
1427bool VIEW::areRequiredLayersEnabled( int aLayerId ) const
1428{
1429 auto it = m_layers.find( aLayerId );
1430
1431 if( it == m_layers.end() )
1432 return false;
1433
1434 for( int layer : it->second.requiredLayers )
1435 {
1436 // That is enough if just one layer is not enabled
1437
1438 auto it2 = m_layers.find( layer );
1439
1440 if( it2 == m_layers.end() || !it2->second.visible )
1441 return false;
1442
1443 if( !areRequiredLayersEnabled( layer ) )
1444 return false;
1445 }
1446
1447 return true;
1448}
1449
1450
1452{
1453 BOX2I r;
1454
1455 r.SetMaximum();
1456
1457 for( const auto& [_, l] : m_layers )
1458 {
1459 if( IsCached( l.id ) )
1460 {
1461 RECACHE_ITEM_VISITOR visitor( this, m_gal, l.id );
1462 l.items->Query( r, visitor );
1463 }
1464 }
1465}
1466
1467
1469{
1470 if( !m_gal->IsVisible() || !m_gal->IsInitialized() )
1471 return;
1472
1473 unsigned int cntGeomUpdate = 0;
1474 bool anyUpdated = false;
1475
1476 for( VIEW_ITEM* item : *m_allItems )
1477 {
1478 if( !item )
1479 continue;
1480
1481 auto vpd = item->viewPrivData();
1482
1483 if( !vpd )
1484 continue;
1485
1486 if( vpd->m_requiredUpdate != NONE )
1487 {
1488 anyUpdated = true;
1489
1490 if( vpd->m_requiredUpdate & ( GEOMETRY | LAYERS ) )
1491 {
1492 cntGeomUpdate++;
1493 }
1494 }
1495 }
1496
1497 unsigned int cntTotal = m_allItems->size();
1498
1499 double ratio = (double) cntGeomUpdate / (double) cntTotal;
1500
1501 // Optimization to improve view update time. If a lot of items (say, 30%) have their
1502 // bboxes/geometry changed it's way faster (around 10 times) to rebuild the R-Trees
1503 // from scratch rather than update the bbox of each changed item. Pcbnew does multiple
1504 // full geometry updates during file load, this can save a solid 30 seconds on load time
1505 // for larger designs...
1506
1507 if( ratio > 0.3 )
1508 {
1509 auto allItems = *m_allItems;
1510
1511 // kill all Rtrees
1512 for( auto& [_, layer] : m_layers )
1513 layer.items->RemoveAll();
1514
1515 // and re-insert items from scratch
1516 for( VIEW_ITEM* item : allItems )
1517 {
1518 if( !item )
1519 continue;
1520
1521 const BOX2I bbox = item->ViewBBox();
1522 item->m_viewPrivData->m_bbox = bbox;
1523
1524 std::vector<int> layers = item->ViewGetLayers();
1525 item->viewPrivData()->saveLayers( layers );
1526
1527 for( int layer : layers )
1528 {
1529 auto it = m_layers.find( layer );
1530
1531 wxCHECK2_MSG( it != m_layers.end(), continue, wxS( "Invalid layer" ) );
1532
1533 VIEW_LAYER& l = it->second;
1534 l.items->Insert( item, bbox );
1536 }
1537
1538 item->viewPrivData()->m_requiredUpdate &= ~( LAYERS | GEOMETRY );
1539 }
1540 }
1541
1542 if( anyUpdated )
1543 {
1545
1546 for( VIEW_ITEM* item : *m_allItems.get() )
1547 {
1548 if( item && item->viewPrivData() && item->viewPrivData()->m_requiredUpdate != NONE )
1549 {
1550 invalidateItem( item, item->viewPrivData()->m_requiredUpdate );
1551 item->viewPrivData()->m_requiredUpdate = NONE;
1552 }
1553 }
1554 }
1555
1556 KI_TRACE( traceGalProfile, wxS( "View update: total items %u, geom %u anyUpdated %u\n" ),
1557 cntTotal, cntGeomUpdate, (unsigned) anyUpdated );
1558}
1559
1560
1561void VIEW::UpdateAllItems( int aUpdateFlags )
1562{
1563 for( VIEW_ITEM* item : *m_allItems )
1564 {
1565 if( item && item->viewPrivData() )
1566 item->viewPrivData()->m_requiredUpdate |= aUpdateFlags;
1567 }
1568}
1569
1570
1572 std::function<bool( VIEW_ITEM* )> aCondition )
1573{
1574 for( VIEW_ITEM* item : *m_allItems )
1575 {
1576 if( !item )
1577 continue;
1578
1579 if( aCondition( item ) )
1580 {
1581 if( item->viewPrivData() )
1582 item->viewPrivData()->m_requiredUpdate |= aUpdateFlags;
1583 }
1584 }
1585}
1586
1587
1588void VIEW::UpdateAllItemsConditionally( std::function<int( VIEW_ITEM* )> aItemFlagsProvider )
1589{
1590 for( VIEW_ITEM* item : *m_allItems )
1591 {
1592 if( !item )
1593 continue;
1594
1595 if( item->viewPrivData() )
1596 item->viewPrivData()->m_requiredUpdate |= aItemFlagsProvider( item );
1597 }
1598}
1599
1600
1601
1602std::unique_ptr<VIEW> VIEW::DataReference() const
1603{
1604 std::unique_ptr<VIEW> ret = std::make_unique<VIEW>();
1605 ret->m_allItems = m_allItems;
1606 ret->m_layers = m_layers;
1607 ret->sortOrderedLayers();
1608 return ret;
1609}
1610
1611
1612void VIEW::SetVisible( VIEW_ITEM* aItem, bool aIsVisible )
1613{
1614 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1615
1616 if( !viewData )
1617 return;
1618
1619 bool cur_visible = viewData->m_flags & VISIBLE;
1620
1621 if( cur_visible != aIsVisible )
1622 {
1623 if( aIsVisible )
1624 viewData->m_flags |= VISIBLE;
1625 else
1626 viewData->m_flags &= ~VISIBLE;
1627
1628 Update( aItem, APPEARANCE | COLOR );
1629 }
1630}
1631
1632
1633void VIEW::Hide( VIEW_ITEM* aItem, bool aHide, bool aHideOverlay )
1634{
1635 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1636
1637 if( !viewData )
1638 return;
1639
1640 if( !( viewData->m_flags & VISIBLE ) )
1641 return;
1642
1643 if( aHideOverlay )
1644 viewData->m_flags |= OVERLAY_HIDDEN;
1645
1646 if( aHide )
1647 viewData->m_flags |= HIDDEN;
1648 else
1649 viewData->m_flags &= ~( HIDDEN | OVERLAY_HIDDEN );
1650
1651 Update( aItem, APPEARANCE );
1652}
1653
1654
1655bool VIEW::IsVisible( const VIEW_ITEM* aItem ) const
1656{
1657 const VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1658
1659 return viewData && ( viewData->m_flags & VISIBLE );
1660}
1661
1662
1663bool VIEW::IsHiddenOnOverlay( const VIEW_ITEM* aItem ) const
1664{
1665 const VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1666
1667 return viewData && ( viewData->m_flags & OVERLAY_HIDDEN );
1668}
1669
1670
1671bool VIEW::HasItem( const VIEW_ITEM* aItem ) const
1672{
1673 const VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1674
1675 return viewData && viewData->m_view == this;
1676}
1677
1678
1679void VIEW::Update( const VIEW_ITEM* aItem ) const
1680{
1681 Update( aItem, ALL );
1682}
1683
1684
1685void VIEW::Update( const VIEW_ITEM* aItem, int aUpdateFlags ) const
1686{
1687 VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1688
1689 if( !viewData )
1690 return;
1691
1692 assert( aUpdateFlags != NONE );
1693
1694 viewData->m_requiredUpdate |= aUpdateFlags;
1695}
1696
1697
1698std::shared_ptr<VIEW_OVERLAY> VIEW::MakeOverlay()
1699{
1700 std::shared_ptr<VIEW_OVERLAY> overlay = std::make_shared<VIEW_OVERLAY>();
1701
1702 Add( overlay.get() );
1703 return overlay;
1704}
1705
1706
1708{
1709 if( !m_preview )
1710 return;
1711
1712 m_preview->Clear();
1713
1714 for( VIEW_ITEM* item : m_ownedItems )
1715 delete item;
1716
1717 m_ownedItems.clear();
1718 Update( m_preview.get() );
1719}
1720
1721
1723{
1724 m_preview.reset( new KIGFX::VIEW_GROUP() );
1725 Add( m_preview.get() );
1726}
1727
1728
1729void VIEW::AddToPreview( VIEW_ITEM* aItem, bool aTakeOwnership )
1730{
1731 Hide( aItem, false );
1732 m_preview->Add( aItem );
1733
1734 if( aTakeOwnership )
1735 m_ownedItems.push_back( aItem );
1736
1737 SetVisible( m_preview.get(), true );
1738 Hide( m_preview.get(), false );
1739 Update( m_preview.get() );
1740}
1741
1742
1743void VIEW::ShowPreview( bool aShow )
1744{
1745 SetVisible( m_preview.get(), aShow );
1746}
1747
1748
1749} // namespace KIGFX
int color
Definition: DXF_plotter.cpp:63
constexpr int ARC_LOW_DEF
Definition: base_units.h:128
constexpr BOX2I BOX2ISafe(const BOX2D &aInput)
Definition: box2.h:929
constexpr void SetMaximum()
Definition: box2.h:80
constexpr void SetOrigin(const Vec &pos)
Definition: box2.h:237
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:146
constexpr size_type GetWidth() const
Definition: box2.h:214
constexpr Vec Centre() const
Definition: box2.h:97
constexpr void SetSize(const SizeVec &size)
Definition: box2.h:248
constexpr size_type GetHeight() const
Definition: box2.h:215
constexpr coord_type GetLeft() const
Definition: box2.h:228
constexpr bool Contains(const Vec &aPoint) const
Definition: box2.h:168
constexpr coord_type GetRight() const
Definition: box2.h:217
constexpr const SizeVec & GetSize() const
Definition: box2.h:206
constexpr void SetEnd(coord_type x, coord_type y)
Definition: box2.h:297
constexpr coord_type GetTop() const
Definition: box2.h:229
constexpr coord_type GetBottom() const
Definition: box2.h:222
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 bool IsOpenGlEngine()
Return true if the GAL engine is a OpenGL based type.
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:59
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:43
virtual unsigned int GetSize() const
Return the number of stored items.
Definition: view_group.cpp:83
virtual VIEW_ITEM * GetItem(unsigned int aIdx) const
Definition: view_group.cpp:89
bool storesGroups() const
Return information if the item uses at least one group id (ie.
Definition: view.cpp:142
std::vector< int > m_layers
Definition: view.cpp:220
int requiredUpdate() const
Return current update flag for an item.
Definition: view.cpp:189
int m_requiredUpdate
Flag required for updating.
Definition: view.cpp:212
int m_flags
Visibility flags.
Definition: view.cpp:211
void reorderGroups(std::unordered_map< int, int > aReorderMap)
Reorder the stored groups (to facilitate reordering of layers).
Definition: view.cpp:154
int m_cachedIndex
Cached index in m_allItems.
Definition: view.cpp:214
void deleteGroups()
Remove all of the stored group ids.
Definition: view.cpp:130
bool isRenderable() const
Return if the item should be drawn or not.
Definition: view.cpp:205
int m_drawPriority
Order to draw this item in a layer, lowest first.
Definition: view.cpp:213
VIEW * m_view
Current dynamic view the item is assigned to.
Definition: view.cpp:210
std::pair< int, int > * m_groups
layer_number:group_id pairs for each layer the item occupies.
Definition: view.cpp:216
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:84
BOX2I m_bbox
Stores layer numbers used by the item.
Definition: view.cpp:222
void setGroup(int aLayer, int aGroup)
Set a group id for the item and the layer combination.
Definition: view.cpp:101
void saveLayers(const std::vector< int > &aLayers)
Save layers used by the item.
Definition: view.cpp:174
int GetFlags() const
Definition: view.cpp:70
void clearUpdateFlags()
Mark an item as already updated, so it is not going to be redrawn.
Definition: view.cpp:197
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:86
virtual const BOX2I ViewBBox() const =0
Return the bounding box of the item covering all its layers.
double m_forcedTransparency
Additional transparency for diff'ing items.
Definition: view_item.h:210
VIEW_ITEM_DATA * viewPrivData() const
Definition: view_item.h:161
virtual void ViewDraw(int aLayer, VIEW *aView) const
Draw the parts of the object belonging to layer aLayer.
Definition: view_item.h:127
virtual std::vector< int > ViewGetLayers() const =0
Return the all the layers within the VIEW the object is painted on.
virtual wxString GetClass() const =0
Return the class name.
virtual double ViewGetLOD(int aLayer, const VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition: view_item.h:155
VIEW_ITEM_DATA * m_viewPrivData
Definition: view_item.h:209
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:66
double GetScale() const
Definition: view.h:276
void SetMirror(bool aMirrorX, bool aMirrorY)
Control the mirroring of the VIEW.
Definition: view.cpp:557
void ShowPreview(bool aShow=true)
Definition: view.cpp:1743
double m_maxScale
Definition: view.h:882
BOX2D GetViewport() const
Return the current viewport visible area rectangle.
Definition: view.cpp:530
void CopySettings(const VIEW *aOtherView)
Copy layers and visibility settings from another view.
Definition: view.cpp:505
virtual void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 })
Set the scaling factor, zooming around a given anchor point.
Definition: view.cpp:570
static constexpr int TOP_LAYER_MODIFIER
Rendering order modifier for layers that are marked as top layers.
Definition: view.h:748
void draw(VIEW_ITEM *aItem, int aLayer, bool aImmediate=false)
Draw an item, but on a specified layers.
Definition: view.cpp:1053
bool m_reverseDrawOrder
Flag to reverse the draw order when using draw priority.
Definition: view.h:903
void UpdateAllLayersOrder()
Do everything that is needed to apply the rendering order of layers.
Definition: view.cpp:906
void updateItemColor(VIEW_ITEM *aItem, int aLayer)
Update colors that are used for an item to be drawn.
Definition: view.cpp:1292
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition: view.cpp:542
void SetRequired(int aLayerId, int aRequiredId, bool aRequired=true)
Mark the aRequiredId layer as required for the aLayerId layer.
Definition: view.cpp:408
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:486
static bool compareRenderingOrder(VIEW_LAYER *aI, VIEW_LAYER *aJ)
Determine rendering order of layers. Used in display order sorting function.
Definition: view.h:843
int GetLayerOrder(int aLayer) const
Return rendering order of a particular layer.
Definition: view.cpp:664
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:298
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:341
void ClearTargets()
Clear targets that are marked as dirty.
Definition: view.cpp:1158
virtual void EnableTopLayer(bool aEnable)
Enable or disable display of the top layer.
Definition: view.cpp:866
bool m_mirrorX
Definition: view.h:884
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition: view.cpp:775
bool m_mirrorY
Definition: view.h:885
std::shared_ptr< std::vector< VIEW_ITEM * > > m_allItems
Flat list of all items.
Definition: view.h:871
std::shared_ptr< VIEW_OVERLAY > MakeOverlay()
Definition: view.cpp:1698
void SetGAL(GAL *aGal)
Assign a rendering device for the VIEW.
Definition: view.cpp:511
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:420
std::vector< VIEW_ITEM * > m_ownedItems
Definition: view.h:859
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:1685
void invalidateItem(VIEW_ITEM *aItem, int aUpdateFlags)
Manage dirty flags & redraw queuing when updating an item.
Definition: view.cpp:1238
const VECTOR2I & GetScreenPixelSize() const
Return the size of the our rendering area in pixels.
Definition: view.cpp:1202
bool HasItem(const VIEW_ITEM *aItem) const
Indicates whether or not the given item has been added to the view.
Definition: view.cpp:1671
virtual int GetTopLayer() const
Definition: view.cpp:830
PAINTER * m_painter
PAINTER contains information how do draw items.
Definition: view.h:888
virtual void Redraw()
Immediately redraws the whole view.
Definition: view.cpp:1177
void Clear()
Remove all items from the view.
Definition: view.cpp:1143
std::set< unsigned int > m_topLayers
The set of layers that are displayed on the top.
Definition: view.h:874
bool m_enableOrderModifier
Whether to use rendering order modifier or not.
Definition: view.h:862
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:467
bool IsHiddenOnOverlay(const VIEW_ITEM *aItem) const
Definition: view.cpp:1663
void ClearTopLayers()
Remove all layers from the on-the-top set (they are no longer displayed over the rest of layers).
Definition: view.cpp:891
void InitPreview()
Definition: view.cpp:1722
void ClearPreview()
Definition: view.cpp:1707
void MarkClean()
Force redraw of view on the next rendering.
Definition: view.h:668
void updateItemGeometry(VIEW_ITEM *aItem, int aLayer)
Update all information needed to draw an item.
Definition: view.cpp:1310
static constexpr int VIEW_MAX_LAYERS
Maximum number of layers that may be shown.
Definition: view.h:745
double m_minScale
Definition: view.h:881
double m_scale
Definition: view.h:879
void updateLayers(VIEW_ITEM *aItem)
Update set of layers that an item occupies.
Definition: view.cpp:1372
void RecacheAllItems()
Rebuild GAL display lists.
Definition: view.cpp:1451
bool areRequiredLayersEnabled(int aLayerId) const
Check if every layer required by the aLayerId layer is enabled.
Definition: view.cpp:1427
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:628
int m_nextDrawPriority
The next sequential drawing priority.
Definition: view.h:900
void sortOrderedLayers()
Sort m_orderedLayers when layer rendering order has changed.
Definition: view.cpp:1277
bool m_useDrawPriority
Flag to respect draw priority when drawing items.
Definition: view.h:897
void UpdateItems()
Iterate through the list of items that asked for updating and updates them.
Definition: view.cpp:1468
bool IsCached(int aLayer) const
Return true if the layer is cached.
Definition: view.h:646
std::pair< VIEW_ITEM *, int > LAYER_ITEM_PAIR
Definition: view.h:70
void SortLayers(std::vector< int > &aLayers) const
Change the order of given layer ids, so after sorting the order corresponds to layers rendering order...
Definition: view.cpp:670
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition: view.cpp:1561
std::unique_ptr< KIGFX::VIEW_GROUP > m_preview
Definition: view.h:858
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:226
virtual ~VIEW()
Definition: view.cpp:292
GAL * m_gal
Interface to #PAINTER that is used to draw items.
Definition: view.h:891
std::map< int, VIEW_LAYER > m_layers
The set of possible displayed layers and its properties.
Definition: view.h:865
std::unique_ptr< VIEW > DataReference() const
Return a new VIEW object that shares the same set of VIEW_ITEMs and LAYERs.
Definition: view.cpp:1602
void Hide(VIEW_ITEM *aItem, bool aHide=true, bool aHideOverlay=false)
Temporarily hide the item in the view (e.g.
Definition: view.cpp:1633
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:839
void AddToPreview(VIEW_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1729
void UpdateLayerColor(int aLayer)
Apply the new coloring scheme held by RENDER_SETTINGS in case that it has changed.
Definition: view.cpp:754
void MarkDirty()
Force redraw of view on the next rendering.
Definition: view.h:659
BOX2D m_boundary
Definition: view.h:880
void SetCenter(const VECTOR2D &aCenter)
Set the center point of the VIEW (i.e.
Definition: view.cpp:596
std::vector< VIEW_LAYER * > m_orderedLayers
Sorted list of pointers to members of m_layers.
Definition: view.h:868
void clearGroupCache()
Clear cached GAL group numbers (ONLY numbers stored in VIEW_ITEMs, not group objects used by GAL).
Definition: view.cpp:1226
VECTOR2D m_center
Center point of the VIEW (the point at which we are looking at).
Definition: view.h:877
void SetLayerOrder(int aLayer, int aRenderingOrder)
Set rendering order of a particular layer.
Definition: view.cpp:656
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition: view.h:639
void updateBbox(VIEW_ITEM *aItem)
Update bounding box of an item.
Definition: view.cpp:1347
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition: view.cpp:1655
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:1571
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1612
void ReorderLayerData(std::unordered_map< int, int > aReorderMap)
Remap the data between layer ids without invalidating that data.
Definition: view.cpp:680
void redrawRect(const BOX2I &aRect)
Redraw contents within rectangle aRect.
Definition: view.cpp:1010
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
Definition: matrix3x3.h:295
A small class to help profiling.
Definition: profile.h:49
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition: profile.h:88
double msecs(bool aSinceLast=false)
Definition: profile.h:149
Represent a set of closed polygons.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
void Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
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.
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
The Cairo implementation of the graphics abstraction layer.
Definition: eda_group.h:33
@ COLOR
Color has changed.
Definition: view_item.h:54
@ INITIAL_ADD
Item is being added to the view.
Definition: view_item.h:57
@ NONE
No updates are required.
Definition: view_item.h:52
@ REPAINT
Item needs to be redrawn.
Definition: view_item.h:58
@ APPEARANCE
Visibility flag has changed.
Definition: view_item.h:53
@ GEOMETRY
Position or shape has changed.
Definition: view_item.h:55
@ LAYERS
Layers have changed.
Definition: view_item.h:56
@ ALL
All except INITIAL_ADD.
Definition: view_item.h:59
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
Definition: definitions.h:38
@ TARGET_CACHED
Main rendering target (cached)
Definition: definitions.h:37
@ TARGET_OVERLAY
Items that may change while the view stays the same (noncached)
Definition: definitions.h:39
@ HIDDEN
Item is temporarily hidden (usually in favor of a being drawn from an overlay, such as a SELECTION).
Definition: view_item.h:70
@ OVERLAY_HIDDEN
Item is temporarily hidden from being drawn on an overlay.
Definition: view_item.h:71
@ VISIBLE
Item is visible (in general)
Definition: view_item.h:66
std::shared_ptr< PNS_LOG_VIEWER_OVERLAY > overlay
Definition: playground.cpp:46
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:1215
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:950
DRAW_ITEM_VISITOR(VIEW *aView, int aLayer, bool aUseDrawPriority, bool aReverseDrawOrder)
Definition: view.cpp:940
int layers[VIEW_MAX_LAYERS]
Definition: view.cpp:1002
std::vector< VIEW_ITEM * > drawItems
Definition: view.cpp:1004
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:1118
RECACHE_ITEM_VISITOR(VIEW *aView, GAL *aGal, int aLayer)
Definition: view.cpp:1111
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:736
UPDATE_COLOR_VISITOR(int aLayer, PAINTER *aPainter, GAL *aGal)
Definition: view.cpp:729
UPDATE_DEPTH_VISITOR(int aLayer, int aDepth, GAL *aGal)
Definition: view.cpp:808
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:815
bool diffLayer
Layer should be drawn differentially over lower layers.
Definition: view.h:757
int renderingOrder
Rendering order of this layer.
Definition: view.h:762
bool hasNegatives
Layer should be drawn separately to not delete lower layers.
Definition: view.h:760
bool visible
Is the layer to be rendered?
Definition: view.h:753
bool displayOnly
Is the layer display only?
Definition: view.h:754
std::shared_ptr< VIEW_RTREE > items
R-tree indexing all items on this layer.
Definition: view.h:761
RENDER_TARGET target
Where the layer should be rendered.
Definition: view.h:764
int id
Layer ID.
Definition: view.h:763
int delta
wxLogTrace helper definitions.
#define KI_TRACE(aWhat,...)
VECTOR2< double > VECTOR2D
Definition: vector2d.h:694