1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2018-2021 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "gerbview_draw_panel_gal.h"
21 #include <view/view.h>
22 #include <view/wx_view_controls.h>
23 #include <gerbview_painter.h>
24 #include <drawing_sheet/ds_proxy_view_item.h>
25 #include <zoom_defines.h>
26 
27 #include <gerbview_frame.h>
28 #include <gal/graphics_abstraction_layer.h>
29 #include <pgm_base.h>
30 #include <settings/settings_manager.h>
31 
32 #include <gerber_file_image.h>
33 #include <gerber_file_image_list.h>
34 
35 #include <functional>
36 #include <memory>
37 
38 using namespace std::placeholders;
39 
40 
GERBVIEW_DRAW_PANEL_GAL(wxWindow * aParentWindow,wxWindowID aWindowId,const wxPoint & aPosition,const wxSize & aSize,KIGFX::GAL_DISPLAY_OPTIONS & aOptions,GAL_TYPE aGalType)41 GERBVIEW_DRAW_PANEL_GAL::GERBVIEW_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWindowId,
42                                                   const wxPoint& aPosition, const wxSize& aSize,
43                                                   KIGFX::GAL_DISPLAY_OPTIONS& aOptions,
44                                                   GAL_TYPE aGalType ) :
45 EDA_DRAW_PANEL_GAL( aParentWindow, aWindowId, aPosition, aSize, aOptions, aGalType )
46 {
47     m_view = new KIGFX::VIEW( true );
48     m_view->SetGAL( m_gal );
49     GetGAL()->SetWorldUnitLength( 1.0/IU_PER_MM /* 10 nm */ / 25.4 /* 1 inch in mm */ );
50 
51     m_painter = std::make_unique<KIGFX::GERBVIEW_PAINTER>( m_gal );
52     m_view->SetPainter( m_painter.get() );
53 
54     // This fixes the zoom in and zoom out limits:
55     m_view->SetScaleLimits( ZOOM_MAX_LIMIT_GERBVIEW, ZOOM_MIN_LIMIT_GERBVIEW );
56 
57     m_viewControls = new KIGFX::WX_VIEW_CONTROLS( m_view, this );
58 
59     setDefaultLayerDeps();
60 
61     // Load display options (such as filled/outline display of items).
62     auto frame = static_cast< GERBVIEW_FRAME* >( GetParentEDAFrame() );
63 
64     if( frame )
65     {
66         auto& displ_opts = frame->GetDisplayOptions();
67         auto rs = static_cast<KIGFX::GERBVIEW_RENDER_SETTINGS*>(
68                 m_view->GetPainter()->GetSettings() );
69 
70         rs->LoadDisplayOptions( displ_opts );
71         rs->LoadColors( Pgm().GetSettingsManager().GetColorSettings() );
72     }
73 }
74 
75 
~GERBVIEW_DRAW_PANEL_GAL()76 GERBVIEW_DRAW_PANEL_GAL::~GERBVIEW_DRAW_PANEL_GAL()
77 {
78 }
79 
80 
SetHighContrastLayer(int aLayer)81 void GERBVIEW_DRAW_PANEL_GAL::SetHighContrastLayer( int aLayer )
82 {
83     // Set display settings for high contrast mode
84     KIGFX::RENDER_SETTINGS* rSettings = m_view->GetPainter()->GetSettings();
85 
86     SetTopLayer( aLayer );
87 
88     rSettings->ClearHighContrastLayers();
89     rSettings->SetLayerIsHighContrast( aLayer );
90     rSettings->SetLayerIsHighContrast( GERBER_DCODE_LAYER( aLayer ) );
91 
92     m_view->UpdateAllLayersColor();
93 }
94 
95 
GetMsgPanelInfo(EDA_DRAW_FRAME * aFrame,std::vector<MSG_PANEL_ITEM> & aList)96 void GERBVIEW_DRAW_PANEL_GAL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
97                                                std::vector<MSG_PANEL_ITEM>& aList )
98 {
99 
100 }
101 
102 
OnShow()103 void GERBVIEW_DRAW_PANEL_GAL::OnShow()
104 {
105     GERBVIEW_FRAME* frame = dynamic_cast<GERBVIEW_FRAME*>( GetParentEDAFrame() );
106 
107     if( frame )
108     {
109         SetTopLayer( frame->GetActiveLayer() );
110         auto& displ_opts = frame->GetDisplayOptions();
111         static_cast<KIGFX::GERBVIEW_RENDER_SETTINGS*>(
112             m_view->GetPainter()->GetSettings() )->LoadDisplayOptions( displ_opts );
113     }
114 
115     m_view->RecacheAllItems();
116 }
117 
118 
SwitchBackend(GAL_TYPE aGalType)119 bool GERBVIEW_DRAW_PANEL_GAL::SwitchBackend( GAL_TYPE aGalType )
120 {
121     bool rv = EDA_DRAW_PANEL_GAL::SwitchBackend( aGalType );
122 
123     // The next onPaint event will call m_view->UpdateItems() that is very time consuming
124     // after switching to opengl. Clearing m_view and rebuild it is much faster
125     if( aGalType == GAL_TYPE_OPENGL )
126     {
127         GERBVIEW_FRAME* frame = dynamic_cast<GERBVIEW_FRAME*>( GetParentEDAFrame() );
128 
129         if( frame )
130         {
131             m_view->Clear();
132 
133             for( int layer = GERBER_DRAWLAYERS_COUNT-1; layer>= 0; --layer )
134             {
135                 GERBER_FILE_IMAGE* gerber = frame->GetImagesList()->GetGbrImage( layer );
136 
137                 if( gerber == nullptr )    // Graphic layer not yet used
138                     continue;
139 
140                 for( GERBER_DRAW_ITEM* item : gerber->GetItems() )
141                 {
142                     m_view->Add (item );
143                 }
144             }
145         }
146     }
147 
148     setDefaultLayerDeps();
149 
150     GetGAL()->SetWorldUnitLength( 1.0/IU_PER_MM /* 10 nm */ / 25.4 /* 1 inch in mm */ );
151 
152     return rv;
153 }
154 
155 
setDefaultLayerDeps()156 void GERBVIEW_DRAW_PANEL_GAL::setDefaultLayerDeps()
157 {
158     // caching makes no sense for Cairo and other software renderers
159     auto target = m_backend == GAL_TYPE_OPENGL ? KIGFX::TARGET_CACHED : KIGFX::TARGET_NONCACHED;
160 
161     for( int i = 0; i < KIGFX::VIEW::VIEW_MAX_LAYERS; i++ )
162         m_view->SetLayerTarget( i, target );
163 
164     m_view->SetLayerDisplayOnly( LAYER_DCODES );
165     m_view->SetLayerDisplayOnly( LAYER_NEGATIVE_OBJECTS );
166     m_view->SetLayerDisplayOnly( LAYER_GERBVIEW_GRID );
167     m_view->SetLayerDisplayOnly( LAYER_GERBVIEW_AXES );
168     m_view->SetLayerDisplayOnly( LAYER_GERBVIEW_BACKGROUND );
169     m_view->SetLayerDisplayOnly( LAYER_DRAWINGSHEET );
170 
171     m_view->SetLayerTarget( LAYER_SELECT_OVERLAY, KIGFX::TARGET_OVERLAY );
172     m_view->SetLayerDisplayOnly( LAYER_SELECT_OVERLAY );
173 
174     m_view->SetLayerTarget( LAYER_GP_OVERLAY, KIGFX::TARGET_OVERLAY );
175     m_view->SetLayerDisplayOnly( LAYER_GP_OVERLAY );
176 }
177 
178 
SetDrawingSheet(DS_PROXY_VIEW_ITEM * aDrawingSheet)179 void GERBVIEW_DRAW_PANEL_GAL::SetDrawingSheet( DS_PROXY_VIEW_ITEM* aDrawingSheet )
180 {
181     m_drawingSheet.reset( aDrawingSheet );
182     m_view->Add( m_drawingSheet.get() );
183 }
184 
185 
SetTopLayer(int aLayer)186 void GERBVIEW_DRAW_PANEL_GAL::SetTopLayer( int aLayer )
187 {
188     m_view->ClearTopLayers();
189 
190     for( int i = 0; i < GERBER_DRAWLAYERS_COUNT; ++i )
191     {
192         m_view->SetLayerOrder( GERBER_DCODE_LAYER( GERBER_DRAW_LAYER( i ) ),
193                                GERBER_DRAW_LAYER( 2 * i ) );
194         m_view->SetLayerOrder( GERBER_DRAW_LAYER( i ), GERBER_DRAW_LAYER( ( 2 * i ) + 1 ) );
195     }
196 
197     m_view->SetTopLayer( aLayer );
198 
199     // Move DCODE layer to the top
200     m_view->SetTopLayer( GERBER_DCODE_LAYER( aLayer ) );
201 
202     m_view->SetTopLayer( LAYER_SELECT_OVERLAY );
203 
204     m_view->SetTopLayer( LAYER_GP_OVERLAY );
205 
206     m_view->UpdateAllLayersOrder();
207 }
208 
209 
GetDefaultViewBBox() const210 BOX2I GERBVIEW_DRAW_PANEL_GAL::GetDefaultViewBBox() const
211 {
212     // Even in Gervbview, LAYER_DRAWINGSHEET controls the visibility of the drawingsheet
213     if( m_drawingSheet && m_view->IsLayerVisible( LAYER_DRAWINGSHEET ) )
214         return m_drawingSheet->ViewBBox();
215 
216     return BOX2I();
217 }
218