KiCad PCB EDA Suite
Loading...
Searching...
No Matches
bitmap.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) 2011 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
5 * Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25
26#include <wx/image.h>
27#include <wx/bitmap.h>
28#include <wx/gdicmn.h>
29#include <wx/mstream.h>
30#include <wx/menu.h>
31#include <wx/menuitem.h>
32#include <wx/aui/auibar.h>
33#include <wx/dcclient.h>
34#include <wx/dcmemory.h>
35
36#include <cstdint>
37#include <mutex>
38#include <unordered_map>
39
40#include <asset_archive.h>
41#include <bitmaps.h>
42#include <bitmap_store.h>
43#include <bitmaps/bitmap_opaque.h> // for pcb_calculator compatibility shim
44#include <pgm_base.h>
45#include <eda_base_frame.h>
46#include <eda_draw_frame.h>
47#include <paths.h>
48#include <kiplatform/ui.h>
49
50
51static std::unique_ptr<BITMAP_STORE> s_BitmapStore;
52
53
56 int scale;
57
58 bool operator==( SCALED_BITMAP_ID const& other ) const noexcept
59 {
60 return bitmap == other.bitmap && scale == other.scale;
61 }
62};
63
64
65namespace std {
66 template<> struct hash<SCALED_BITMAP_ID>
67 {
69 typedef std::size_t result_type;
70
71 result_type operator()( argument_type const& id ) const noexcept
72 {
73 static const bool sz64 = sizeof( uintptr_t ) == 8;
74 static const size_t mask = sz64 ? 0xF000000000000000uLL : 0xF0000000uL;
75 static const size_t offset = sz64 ? 60 : 28;
76
77 // The hash only needs to be fast and simple, not necessarily accurate - a collision
78 // only makes things slower, not broken. BITMAPS is a pointer, so the most
79 // significant several bits are generally going to be the same for all. Just convert
80 // it to an integer and stuff the scale factor into those bits.
81 return
82 ( (uintptr_t)( id.bitmap ) & ~mask ) |
83 ( ( (uintptr_t)( id.scale ) & 0xF ) << offset );
84 }
85 };
86}
87
88
89static std::unordered_map<SCALED_BITMAP_ID, wxBitmap> s_ScaledBitmapCache;
90
91static std::mutex s_BitmapCacheMutex;
92
93
95{
96 if( !s_BitmapStore )
97 {
98 wxFileName path( PATHS::GetStockDataPath() + wxT( "/resources" ), wxT( "images.zip" ) );
99 s_BitmapStore = std::make_unique<BITMAP_STORE>();
100 }
101
102 return s_BitmapStore.get();
103}
104
105
106wxBitmap KiBitmap( BITMAPS aBitmap, int aHeightTag )
107{
108 return GetBitmapStore()->GetBitmap( aBitmap, aHeightTag );
109}
110
111
112// TODO: Remove this once pcb_calculator images are moved into the main bitmap system
113wxBitmap KiBitmap( const BITMAP_OPAQUE* aBitmap )
114{
115 wxMemoryInputStream is( aBitmap->png, aBitmap->byteCount );
116 wxImage image( is, wxBITMAP_TYPE_PNG );
117 wxBitmap bitmap( image );
118
119 return bitmap;
120}
121
122
123int KiIconScale( wxWindow* aWindow )
124{
125 #if defined( __WXMSW__)
126 // Basically don't try and scale within kicad and let wx do its thing
127 // with wx introducing bitmap bundles, it will auto scale automatically with dpi
128 // the issue is, none of the scaling factors have any tie to system scaling
129 // this means wx is actually going to scale again causing even more distorted icons
130 return 4;
131 #else
132 const int vert_size = aWindow->ConvertDialogToPixels( wxSize( 0, 8 ) ).y;
133
134 // Autoscale won't exceed unity until the system has quite high resolution,
135 // because we don't want the icons to look obviously scaled on a system
136 // where it's easy to see it.
137
138 if( vert_size > 34 ) return 8;
139 else if( vert_size > 29 ) return 7;
140 else if( vert_size > 24 ) return 6;
141 else return 4;
142 #endif
143}
144
145
146static int get_scale_factor( wxWindow* aWindow )
147{
148 int requested_scale = Pgm().GetCommonSettings()->m_Appearance.icon_scale;
149
150 if( requested_scale > 0 )
151 return requested_scale;
152 else
153 return KiIconScale( aWindow );
154}
155
156
157wxBitmap KiScaledBitmap( BITMAPS aBitmap, wxWindow* aWindow, int aHeight, bool aQuantized )
158{
159 // Bitmap conversions are cached because they can be slow.
160 int scale = get_scale_factor( aWindow );
161
162 if( aQuantized )
163 scale = KiROUND( (double) scale / 4.0 ) * 4;
164
165 SCALED_BITMAP_ID id = { static_cast<BITMAPS>( aBitmap ), scale };
166
167 std::lock_guard<std::mutex> guard( s_BitmapCacheMutex );
168 auto it = s_ScaledBitmapCache.find( id );
169
170 if( it != s_ScaledBitmapCache.end() )
171 {
172 return it->second;
173 }
174 else
175 {
176 wxBitmap bitmap = GetBitmapStore()->GetBitmapScaled( aBitmap, scale, aHeight );
177 return s_ScaledBitmapCache.emplace( id, bitmap ).first->second;
178 }
179}
180
181
183{
184 std::lock_guard<std::mutex> guard( s_BitmapCacheMutex );
185 s_ScaledBitmapCache.clear();
186}
187
188
189wxBitmap KiScaledBitmap( const wxBitmap& aBitmap, wxWindow* aWindow )
190{
191 const int scale = get_scale_factor( aWindow );
192
193 if( scale == 4 )
194 {
195 return wxBitmap( aBitmap );
196 }
197 else
198 {
199 wxImage image = aBitmap.ConvertToImage();
200 image.Rescale( scale * image.GetWidth() / 4, scale * image.GetHeight() / 4,
201 wxIMAGE_QUALITY_BILINEAR );
202
203 return wxBitmap( image );
204 }
205}
206
207
208wxBitmap* KiBitmapNew( BITMAPS aBitmap )
209{
210 wxBitmap* bitmap = new wxBitmap( GetBitmapStore()->GetBitmap( aBitmap ) );
211
212 return bitmap;
213}
214
215
216bool SaveCanvasImageToFile( EDA_DRAW_FRAME* aFrame, const wxString& aFileName,
217 BITMAP_TYPE aBitmapType )
218{
219 wxCHECK( aFrame != nullptr, false );
220
221 bool retv = true;
222
223 // Make a screen copy of the canvas:
224 wxSize image_size = aFrame->GetCanvas()->GetClientSize();
225
226 wxClientDC dc( aFrame->GetCanvas() );
227 wxBitmap bitmap( image_size.x, image_size.y );
228 wxMemoryDC memdc;
229
230 memdc.SelectObject( bitmap );
231 memdc.Blit( 0, 0, image_size.x, image_size.y, &dc, 0, 0 );
232 memdc.SelectObject( wxNullBitmap );
233
234 wxImage image = bitmap.ConvertToImage();
235
236 wxBitmapType type = wxBITMAP_TYPE_PNG;
237 switch( aBitmapType )
238 {
239 case BITMAP_TYPE::PNG: type = wxBITMAP_TYPE_PNG; break;
240 case BITMAP_TYPE::BMP: type = wxBITMAP_TYPE_BMP; break;
241 case BITMAP_TYPE::JPG: type = wxBITMAP_TYPE_JPEG; break;
242 }
243
244 if( !image.SaveFile( aFileName, type ) )
245 retv = false;
246
247 image.Destroy();
248 return retv;
249}
250
251
252void AddBitmapToMenuItem( wxMenuItem* aMenu, const wxBitmap& aImage )
253{
254 // Retrieve the global application show icon option:
255 bool useImagesInMenus = Pgm().GetCommonSettings()->m_Appearance.use_icons_in_menus;
256
257 wxItemKind menu_type = aMenu->GetKind();
258
259 if( useImagesInMenus && menu_type != wxITEM_CHECK && menu_type != wxITEM_RADIO )
260 {
261 aMenu->SetBitmap( aImage );
262 }
263}
264
265
266wxMenuItem* AddMenuItem( wxMenu* aMenu, int aId, const wxString& aText,
267 const wxBitmap& aImage, wxItemKind aType = wxITEM_NORMAL )
268{
269 wxMenuItem* item = new wxMenuItem( aMenu, aId, aText, wxEmptyString, aType );
270 AddBitmapToMenuItem( item, aImage );
271
272 aMenu->Append( item );
273
274 return item;
275}
276
277
278wxMenuItem* AddMenuItem( wxMenu* aMenu, int aId, const wxString& aText,
279 const wxString& aHelpText, const wxBitmap& aImage,
280 wxItemKind aType = wxITEM_NORMAL )
281{
282 wxMenuItem* item = new wxMenuItem( aMenu, aId, aText, aHelpText, aType );
283 AddBitmapToMenuItem( item, aImage );
284
285 aMenu->Append( item );
286
287 return item;
288}
289
290
291wxMenuItem* AddMenuItem( wxMenu* aMenu, wxMenu* aSubMenu, int aId,
292 const wxString& aText, const wxBitmap& aImage )
293{
294 wxMenuItem* item = new wxMenuItem( aMenu, aId, aText );
295 item->SetSubMenu( aSubMenu );
296 AddBitmapToMenuItem( item, aImage );
297
298 aMenu->Append( item );
299
300 return item;
301}
302
303
304wxMenuItem* AddMenuItem( wxMenu* aMenu, wxMenu* aSubMenu, int aId,
305 const wxString& aText, const wxString& aHelpText,
306 const wxBitmap& aImage )
307{
308 wxMenuItem* item = new wxMenuItem( aMenu, aId, aText, aHelpText );
309 item->SetSubMenu( aSubMenu );
310 AddBitmapToMenuItem( item, aImage );
311
312 aMenu->Append( item );
313
314 return item;
315}
wxBitmap * KiBitmapNew(BITMAPS aBitmap)
Allocate a wxBitmap on heap from a memory record, held in a BITMAPS.
Definition: bitmap.cpp:208
static std::unique_ptr< BITMAP_STORE > s_BitmapStore
Definition: bitmap.cpp:51
void ClearScaledBitmapCache()
Wipes out the scaled bitmap cache so that the icon theme can be changed.
Definition: bitmap.cpp:182
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:106
static std::mutex s_BitmapCacheMutex
Definition: bitmap.cpp:91
int KiIconScale(wxWindow *aWindow)
Return the automatic scale factor that would be used for a given window by KiScaledBitmap and KiScale...
Definition: bitmap.cpp:123
wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmap &aImage, wxItemKind aType=wxITEM_NORMAL)
Create and insert a menu item with an icon into aMenu.
Definition: bitmap.cpp:266
BITMAP_STORE * GetBitmapStore()
Definition: bitmap.cpp:94
static std::unordered_map< SCALED_BITMAP_ID, wxBitmap > s_ScaledBitmapCache
Definition: bitmap.cpp:89
wxBitmap KiScaledBitmap(BITMAPS aBitmap, wxWindow *aWindow, int aHeight, bool aQuantized)
Construct a wxBitmap from a memory record, scaling it if device DPI demands it.
Definition: bitmap.cpp:157
static int get_scale_factor(wxWindow *aWindow)
Definition: bitmap.cpp:146
bool SaveCanvasImageToFile(EDA_DRAW_FRAME *aFrame, const wxString &aFileName, BITMAP_TYPE aBitmapType)
Save the current view as an image file.
Definition: bitmap.cpp:216
void AddBitmapToMenuItem(wxMenuItem *aMenu, const wxBitmap &aImage)
Add a bitmap to a menuitem.
Definition: bitmap.cpp:252
BITMAP_TYPE
Definition: bitmap_types.h:42
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
Helper to retrieve bitmaps while handling icon themes and scaling.
Definition: bitmap_store.h:44
wxBitmap GetBitmap(BITMAPS aBitmapId, int aHeight=-1)
Retrieves a bitmap from the given bitmap id.
wxBitmap GetBitmapScaled(BITMAPS aBitmapId, int aScaleFactor, int aHeight=-1)
Retrieves a bitmap from the given bitmap id, scaled to a given factor.
The base class for create windows for drawing purpose.
virtual EDA_DRAW_PANEL_GAL * GetCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
static wxString GetStockDataPath(bool aRespectRunFromBuildDir=true)
Gets the stock (install) data path, which is the base path for things like scripting,...
Definition: paths.cpp:150
Base window classes and related definitions.
STL namespace.
see class PGM_BASE
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:115
const int scale
PNG memory record (file in memory).
Definition: bitmap_opaque.h:26
const unsigned char * png
Definition: bitmap_opaque.h:27
bool operator==(SCALED_BITMAP_ID const &other) const noexcept
Definition: bitmap.cpp:58
BITMAPS bitmap
Definition: bitmap.cpp:55
SCALED_BITMAP_ID argument_type
Definition: bitmap.cpp:68
result_type operator()(argument_type const &id) const noexcept
Definition: bitmap.cpp:71
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85