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