KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
sch_printout.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) 2023 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "sch_printout.h"
22#include <tool/tool_manager.h>
24#include <sch_edit_frame.h>
25#include <math/vector2wx.h>
26#include <pgm_base.h>
29#include <sch_painter.h>
30
31#include <view/view.h>
32#include <gal/gal_print.h>
34#include <gal/painter.h>
35#include <zoom_defines.h>
37#include <string_utils.h>
38#include <wx/dcprint.h>
39#include <wx/log.h>
40#include <wx/dcmemory.h>
41#include <wx/log.h>
42
43
44SCH_PRINTOUT::SCH_PRINTOUT( SCH_EDIT_FRAME* aParent, const wxString& aTitle ) :
45 wxPrintout( aTitle )
46{
47 wxASSERT( aParent != nullptr );
48 m_parent = aParent;
49 m_view = nullptr;
50}
51
52
53void SCH_PRINTOUT::GetPageInfo( int* minPage, int* maxPage, int* selPageFrom, int* selPageTo )
54{
55 *minPage = *selPageFrom = 1;
56 *maxPage = *selPageTo = m_parent->Schematic().Root().CountSheets();
57}
58
59
60bool SCH_PRINTOUT::HasPage( int pageNum )
61{
62 return m_parent->Schematic().Root().CountSheets() >= pageNum;
63}
64
65
66bool SCH_PRINTOUT::OnBeginDocument( int startPage, int endPage )
67{
68 if( !wxPrintout::OnBeginDocument( startPage, endPage ) )
69 return false;
70
71 return true;
72}
73
74
76{
78 sheetList.SortByPageNumbers( false );
79
80 wxCHECK_MSG( page >= 1 && page <= (int)sheetList.size(), false,
81 wxT( "Cannot print invalid page number." ) );
82
83 wxCHECK_MSG( sheetList[ page - 1].LastScreen() != nullptr, false,
84 wxT( "Cannot print page with NULL screen." ) );
85
86 wxString msg;
87 msg.Printf( _( "Print page %d" ), page );
88 m_parent->SetMsgPanel( msg, wxEmptyString );
89
90 SCH_SHEET_PATH oldsheetpath = m_parent->GetCurrentSheet();
91
92 // Switch to the new current sheet
93 m_parent->SetCurrentSheet( sheetList[ page - 1 ] );
98 // Ensure the displayed page number is updated:
99 KIGFX::SCH_VIEW* sch_view = m_parent->GetCanvas()->GetView();
100 sch_view->GetDrawingSheet()->SetPageNumber( TO_UTF8( screen->GetPageNumber() ) );
101 sch_view->GetDrawingSheet()->SetIsFirstPage( screen->GetVirtualPageNumber() == 1 );
102
103 // Print page using the current wxPrinterDC
104 PrintPage( screen, GetDC(), true );
105
106 // Restore the initial current sheet
107 m_parent->SetCurrentSheet( oldsheetpath );
110 screen = m_parent->GetCurrentSheet().LastScreen();
111 sch_view->GetDrawingSheet()->SetPageNumber( TO_UTF8( screen->GetPageNumber() ) );
112 sch_view->GetDrawingSheet()->SetIsFirstPage( screen->GetVirtualPageNumber() == 1 );
113
114 return true;
115}
116
117
119{
120 return KiROUND( aMils * schIUScale.IU_PER_MILS );
121}
122
123
124/*
125 * This is the real print function: print the active screen
126 */
127bool SCH_PRINTOUT::PrintPage( SCH_SCREEN* aScreen, wxDC* aDC, bool aForPrinting )
128{
129 // Note: some data (like paper size) is available only when printing
130 wxDC* dc = aDC;
134 std::unique_ptr<KIGFX::GAL_PRINT> galPrint = KIGFX::GAL_PRINT::Create( options, dc );
135 KIGFX::GAL* gal = galPrint->GetGAL();
136 KIGFX::PRINT_CONTEXT* printCtx = galPrint->GetPrintCtx();
137 std::unique_ptr<KIGFX::SCH_PAINTER> painter = std::make_unique<KIGFX::SCH_PAINTER>( gal );
138 std::unique_ptr<KIGFX::VIEW> view( m_view->DataReference() );
139
140 painter->SetSchematic( &m_parent->Schematic() );
141
146
147 // Target paper size
148 wxRect pageSizePix;
149 wxSize dcPPI = dc->GetPPI();
150
151 if( aForPrinting )
152 pageSizePix = GetLogicalPageRect();
153 else
154 {
155 dc->SetUserScale( 1, 1 );
156
157 if( wxMemoryDC* memdc = dynamic_cast<wxMemoryDC*>( dc ) )
158 {
159 wxBitmap& bm = memdc->GetSelectedBitmap();
160 pageSizePix = wxRect( 0, 0, bm.GetWidth(), bm.GetHeight() );
161 }
162 else
163 {
164 return false;
165 }
166 }
167
168 const VECTOR2D pageSizeIn( (double) pageSizePix.width / dcPPI.x,
169 (double) pageSizePix.height / dcPPI.y );
170 const VECTOR2D pageSizeIU( milsToIU( pageSizeIn.x * 1000 ), milsToIU( pageSizeIn.y * 1000 ) );
171
172 galPrint->SetSheetSize( pageSizeIn );
173
174 view->SetGAL( gal );
175 view->SetPainter( painter.get() );
176 view->SetScaleLimits( ZOOM_MAX_LIMIT_EESCHEMA, ZOOM_MIN_LIMIT_EESCHEMA );
177 view->SetScale( 1.0 );
179
180 // Init the SCH_RENDER_SETTINGS used by the painter used to print schematic
181 SCH_RENDER_SETTINGS* dstSettings = painter->GetSettings();
182
183 dstSettings->m_ShowPinsElectricalType = false;
184
185 // Set the color scheme
186 dstSettings->LoadColors( m_parent->GetColorSettings( false ) );
187
188 if( cfg->m_Printing.use_theme && theme )
189 dstSettings->LoadColors( theme );
190
191 bool printDrawingSheet = cfg->m_Printing.title_block;
192
194
195 if( cfg->m_Printing.background )
196 {
197 if( cfg->m_Printing.use_theme && theme )
198 bgColor = theme->GetColor( LAYER_SCHEMATIC_BACKGROUND );
199 }
200 else
201 {
202 bgColor = COLOR4D::WHITE;
203 }
204
205 dstSettings->SetBackgroundColor( bgColor );
206
207 // The drawing-sheet-item print code is shared between PCBNew and Eeschema, so it's easier
208 // if they just use the PCB layer.
209 dstSettings->SetLayerColor( LAYER_DRAWINGSHEET,
211
212 dstSettings->SetDefaultFont( cfg->m_Appearance.default_font );
213
214 if( cfg->m_Printing.monochrome )
215 {
216 for( int i = 0; i < LAYER_ID_COUNT; ++i )
217 dstSettings->SetLayerColor( i, COLOR4D::BLACK );
218
219 // In B&W mode, draw the background only in white, because any other color
220 // will be replaced by a black background
221 dstSettings->SetBackgroundColor( COLOR4D::WHITE );
222 dstSettings->m_OverrideItemColors = true;
223
224 // Disable print some backgrounds
225 dstSettings->SetPrintBlackAndWhite( true );
226 }
227 else // color enabled
228 {
229 for( int i = 0; i < LAYER_ID_COUNT; ++i )
230 {
231 // Cairo does not support translucent colors on PostScript surfaces
232 // see 'Features support by the PostScript surface' on
233 // https://www.cairographics.org/documentation/using_the_postscript_surface/
234 dstSettings->SetLayerColor( i, dstSettings->GetLayerColor( i ).WithAlpha( 1.0 ) );
235 }
236 }
237
238 dstSettings->SetIsPrinting( true );
239
240 VECTOR2I sheetSizeIU = aScreen->GetPageSettings().GetSizeIU( schIUScale.IU_PER_MILS );
241 BOX2I drawingAreaBBox = BOX2I( VECTOR2I( 0, 0 ), VECTOR2I( sheetSizeIU ) );
242
243 // Enable all layers and use KIGFX::TARGET_NONCACHED to force update drawings
244 // for printing with current GAL instance
245 for( int i = 0; i < KIGFX::VIEW::VIEW_MAX_LAYERS; ++i )
246 {
247 view->SetLayerVisible( i, true );
248 view->SetLayerTarget( i, KIGFX::TARGET_NONCACHED );
249 }
250
251 view->SetLayerVisible( LAYER_DRAWINGSHEET, printDrawingSheet );
252
253 // Don't draw the selection if it's not from the current screen
254 for( EDA_ITEM* item : selTool->GetSelection() )
255 {
256 if( SCH_ITEM* schItem = dynamic_cast<SCH_ITEM*>( item ) )
257 {
258 if( !m_parent->GetScreen()->CheckIfOnDrawList( schItem ) )
259 view->SetLayerVisible( LAYER_SELECT_OVERLAY, false );
260
261 break;
262 }
263 }
264
265 // When is the actual paper size does not match the schematic page size,
266 // we need to adjust the print scale to fit the selected paper size (pageSizeIU)
267 double scaleX = (double) pageSizeIU.x / drawingAreaBBox.GetWidth();
268 double scaleY = (double) pageSizeIU.y / drawingAreaBBox.GetHeight();
269
270 double print_scale = std::min( scaleX, scaleY );
271
272 galPrint->SetNativePaperSize( pageSizeIn, printCtx->HasNativeLandscapeRotation() );
273 gal->SetLookAtPoint( drawingAreaBBox.Centre() );
274 gal->SetZoomFactor( print_scale );
275 gal->SetClearColor( dstSettings->GetBackgroundColor() );
276
277// Clearing the screen for the background color needs the screen set to the page size
278// in pixels. This can ?somehow? prevent some but not all foreground elements from being printed
279// TODO: figure out what's going on here and fix printing. See also board_printout
280 VECTOR2I size = gal->GetScreenPixelSize();
281 gal->ResizeScreen( pageSizePix.GetWidth(),pageSizePix.GetHeight() );
282 gal->ClearScreen();
283 gal->ResizeScreen( size.x, size.y );
284
285 // Needed to use the same order for printing as for screen redraw
286 view->UseDrawPriority( true );
287
288 {
290 view->Redraw();
291 }
292
293 return true;
294}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
BOX2< VECTOR2I > BOX2I
Definition: box2.h:922
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
int GetVirtualPageNumber() const
Definition: base_screen.h:75
const wxString & GetPageNumber() const
Definition: base_screen.cpp:70
constexpr size_type GetWidth() const
Definition: box2.h:214
constexpr Vec Centre() const
Definition: box2.h:97
constexpr size_type GetHeight() const
Definition: box2.h:215
Color settings are a bit different than most of the settings objects in that there can be more than o...
COLOR4D GetColor(int aLayer) const
void SetPageNumber(const std::string &aPageNumber)
Change the page number displayed in the title block.
void SetIsFirstPage(bool aIsFirstPage)
Change if this is first page.
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:96
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition: color4d.h:311
CAIRO_ANTIALIASING_MODE cairo_antialiasing_mode
The grid style to draw the grid in.
static std::unique_ptr< GAL_PRINT > Create(GAL_DISPLAY_OPTIONS &aOptions, wxDC *aDC)
Abstract interface for drawing on a 2D-surface.
virtual void ResizeScreen(int aWidth, int aHeight)
Resize the canvas.
void SetZoomFactor(double aZoomFactor)
void SetLookAtPoint(const VECTOR2D &aPoint)
Get/set the Point in world space to look at.
virtual void ClearScreen()
Clear the screen.
void SetWorldUnitLength(double aWorldUnitLength)
Set the unit length.
void SetClearColor(const COLOR4D &aColor)
const VECTOR2I & GetScreenPixelSize() const
Return GAL canvas size in pixels.
virtual bool HasNativeLandscapeRotation() const =0
void SetLayerColor(int aLayer, const COLOR4D &aColor)
Change the color used to draw a layer.
void SetDefaultFont(const wxString &aFont)
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
void SetPrintBlackAndWhite(bool aPrintBlackAndWhite)
void SetIsPrinting(bool isPrinting)
DS_PROXY_VIEW_ITEM * GetDrawingSheet() const
Definition: sch_view.h:120
static constexpr int VIEW_MAX_LAYERS
Maximum number of layers that may be shown.
Definition: view.h:741
std::unique_ptr< VIEW > DataReference() const
Return a new VIEW object that shares the same set of VIEW_ITEMs and LAYERs.
Definition: view.cpp:1590
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition: page_info.h:171
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:125
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:208
SCH_SHEET & Root() const
Definition: schematic.h:117
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
EESCHEMA_SETTINGS * eeconfig() const
COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Returns a pointer to the active color theme settings.
KIGFX::SCH_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
Schematic editor (Eeschema) main window.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
SCH_SHEET_PATH & GetCurrentSheet() const
SCHEMATIC & Schematic() const
void RecomputeIntersheetRefs()
Update the schematic's page reference map for all global labels, and refresh the labels so that they ...
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
void SetCurrentSheet(const SCH_SHEET_PATH &aSheet)
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:167
bool HasPage(int page) override
bool OnPrintPage(int page) override
void GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) override
SCH_PRINTOUT(SCH_EDIT_FRAME *aParent, const wxString &aTitle)
const KIGFX::SCH_VIEW * m_view
Definition: sch_printout.h:63
SCH_EDIT_FRAME * m_parent
Source VIEW object (note that actual printing only refers to this object)
Definition: sch_printout.h:61
bool PrintPage(SCH_SCREEN *aScreen, wxDC *aDC, bool aForPrinting)
Print the current SCH_SCREEN using a given wxDC.
int milsToIU(int aMils)
bool OnBeginDocument(int startPage, int endPage) override
void SetBackgroundColor(const COLOR4D &aColor) override
Set the background color.
const KIGFX::COLOR4D & GetBackgroundColor() const override
Return current background color settings.
void LoadColors(const COLOR_SETTINGS *aSettings) override
const PAGE_INFO & GetPageSettings() const
Definition: sch_screen.h:134
bool CheckIfOnDrawList(const SCH_ITEM *aItem) const
Definition: sch_screen.cpp:388
SCH_SELECTION & GetSelection()
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void SortByPageNumbers(bool aUpdateVirtualPageNums=true)
Sort the list of sheets by page number.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void UpdateAllScreenReferences() const
Update all the symbol references for this sheet path.
SCH_SCREEN * LastScreen()
int CountSheets() const
Count the number of sheets found in "this" sheet including all of the subsheets.
Definition: sch_sheet.cpp:830
COLOR_SETTINGS * GetColorSettings(const wxString &aName="user")
Retrieve a color settings object that applications can read colors from.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
#define _(s)
#define LAYER_ID_COUNT
Must update this if you add any enums after Gerbview!
Definition: layer_ids.h:612
@ LAYER_DRAWINGSHEET
Sheet frame and title block.
Definition: layer_ids.h:277
@ LAYER_SELECT_OVERLAY
Selected items overlay.
Definition: layer_ids.h:279
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition: layer_ids.h:484
@ LAYER_SCHEMATIC_BACKGROUND
Definition: layer_ids.h:477
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
Definition: definitions.h:38
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:1071
see class PGM_BASE
constexpr double SCH_WORLD_UNIT(1e-7/0.0254)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:403
bool monochrome
Whether or not to print in monochrome.
Definition: app_settings.h:156
bool background
Whether or not to print background color.
Definition: app_settings.h:155
wxString color_theme
Color theme to use for printing.
Definition: app_settings.h:159
bool title_block
Whether or not to print title block.
Definition: app_settings.h:160
bool use_theme
If false, display color theme will be used.
Definition: app_settings.h:158
const double IU_PER_MILS
Definition: base_units.h:77
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695
#define ZOOM_MIN_LIMIT_EESCHEMA
Definition: zoom_defines.h:51
#define ZOOM_MAX_LIMIT_EESCHEMA
Definition: zoom_defines.h:50