KiCad PCB EDA Suite
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 <dick@softplc.com>
5  * Copyright (C) 2017-2018 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/mstream.h>
29 #include <wx/menu.h>
30 #include <wx/menuitem.h>
31 #include <wx/aui/auibar.h>
32 
33 #include <cstdint>
34 #include <mutex>
35 #include <unordered_map>
36 
37 #include <common.h>
38 #include <bitmaps.h>
39 #include <pgm_base.h>
40 #include <wxstruct.h>
41 
42 
45  int scale;
46 
47  bool operator==( SCALED_BITMAP_ID const& other ) const noexcept
48  {
49  return bitmap == other.bitmap && scale == other.scale;
50  }
51 };
52 
53 
54 namespace std {
55  template<> struct hash<SCALED_BITMAP_ID>
56  {
58  typedef std::size_t result_type;
59 
60  result_type operator()( argument_type const& id ) const noexcept
61  {
62  static const bool sz64 = sizeof( uintptr_t ) == 8;
63  static const size_t mask = sz64 ? 0xF000000000000000uLL : 0xF0000000uL;
64  static const size_t offset = sz64 ? 28 : 60;
65 
66  // The hash only needs to be fast and simple, not necessarily accurate - a collision
67  // only makes things slower, not broken. BITMAP_DEF is a pointer, so the most
68  // significant several bits are generally going to be the same for all. Just convert
69  // it to an integer and stuff the scale factor into those bits.
70  return
71  ( (uintptr_t)( id.bitmap ) & ~mask ) |
72  ( ( (uintptr_t)( id.scale ) & 0xF ) << offset );
73  }
74  };
75 }
76 
77 
78 wxBitmap KiBitmap( BITMAP_DEF aBitmap )
79 {
80  wxMemoryInputStream is( aBitmap->png, aBitmap->byteCount );
81  wxImage image( is, wxBITMAP_TYPE_PNG );
82  wxBitmap bitmap( image );
83 
84  return bitmap;
85 }
86 
87 
88 int KiIconScale( wxWindow* aWindow )
89 {
90  const int vert_size = aWindow->ConvertDialogToPixels( wxSize( 0, 8 ) ).y;
91 
92  // Autoscale won't exceed unity until the system has quite high resolution,
93  // because we don't want the icons to look obviously scaled on a system
94  // where it's easy to see it.
95 
96  if( vert_size > 34 ) return 8;
97  else if( vert_size > 29 ) return 7;
98  else if( vert_size > 24 ) return 6;
99  else return 4;
100 }
101 
102 
103 static int get_scale_factor( EDA_BASE_FRAME* aWindow )
104 {
105  const int requested_scale = aWindow->GetIconScale();
106 
107  if( requested_scale > 0 )
108  return requested_scale;
109  else
110  return KiIconScale( aWindow );
111 }
112 
113 
114 wxBitmap KiScaledBitmap( BITMAP_DEF aBitmap, EDA_BASE_FRAME* aWindow )
115 {
116  // Bitmap conversions are cached because they can be slow.
117  static std::unordered_map<SCALED_BITMAP_ID, wxBitmap> bitmap_cache;
118  static std::mutex bitmap_cache_mutex;
119  const int scale = get_scale_factor( aWindow );
120 
121  SCALED_BITMAP_ID id = { aBitmap, scale };
122 
123  std::lock_guard<std::mutex> guard( bitmap_cache_mutex );
124  auto it = bitmap_cache.find( id );
125 
126  if( it != bitmap_cache.end() )
127  {
128  return it->second;
129  }
130  else
131  {
132  wxMemoryInputStream is( aBitmap->png, aBitmap->byteCount );
133  wxImage image( is, wxBITMAP_TYPE_PNG );
134 
135  // Bilinear seems to genuinely look better for these line-drawing icons
136  // than bicubic, despite claims in the wx documentation that bicubic is
137  // "highest quality". I don't recommend changing this. Bicubic looks
138  // blurry and makes me want an eye exam.
139  image.Rescale( scale * image.GetWidth() / 4, scale * image.GetHeight() / 4,
140  wxIMAGE_QUALITY_BILINEAR );
141  return bitmap_cache.emplace( id, wxBitmap( image ) ).first->second;
142  }
143 }
144 
145 
146 void KiScaledSeparator( wxAuiToolBar* aToolbar, EDA_BASE_FRAME* aWindow )
147 {
148  const int scale = get_scale_factor( aWindow );
149 
150  if( scale > 4 )
151  {
152  aToolbar->AddSpacer( 16 * ( scale - 4 ) / 4 );
153  }
154 
155  aToolbar->AddSeparator();
156 
157  if( scale > 4 )
158  {
159  aToolbar->AddSpacer( 16 * ( scale - 4 ) / 4 );
160  }
161 }
162 
163 
164 wxBitmap* KiBitmapNew( BITMAP_DEF aBitmap )
165 {
166  wxMemoryInputStream is( aBitmap->png, aBitmap->byteCount );
167  wxImage image( is, wxBITMAP_TYPE_PNG );
168  wxBitmap* bitmap = new wxBitmap( image );
169 
170  return bitmap;
171 }
172 
173 wxMenuItem* AddMenuItem( wxMenu* aMenu, int aId, const wxString& aText,
174  const wxBitmap& aImage, wxItemKind aType = wxITEM_NORMAL )
175 {
176  wxMenuItem* item;
177 
178  item = new wxMenuItem( aMenu, aId, aText, wxEmptyString, aType );
179 
180  // Retrieve the global applicaton show icon option:
181  bool useImagesInMenus = Pgm().GetUseIconsInMenus();
182 
183  if( useImagesInMenus )
184  {
185  if( aType == wxITEM_CHECK )
186  {
187  #if defined( __WINDOWS__ )
188  item->SetBitmaps( KiBitmap( checked_ok_xpm ), aImage );
189  // A workaround to a strange bug on Windows, wx Widgets 3.0:
190  // size of bitmaps is not taken in account for wxITEM_CHECK menu
191  // unless we call SetFont
192  item->SetFont(*wxNORMAL_FONT);
193  #endif
194  }
195  else
196  item->SetBitmap( aImage );
197  }
198 
199  aMenu->Append( item );
200 
201  return item;
202 }
203 
204 wxMenuItem* AddMenuItem( wxMenu* aMenu, int aId, const wxString& aText,
205  const wxString& aHelpText, const wxBitmap& aImage,
206  wxItemKind aType = wxITEM_NORMAL )
207 {
208  wxMenuItem* item;
209 
210  item = new wxMenuItem( aMenu, aId, aText, aHelpText, aType );
211 
212  // Retrieve the global applicaton show icon option:
213  bool useImagesInMenus = Pgm().GetUseIconsInMenus();
214 
215  if( useImagesInMenus )
216  {
217  if( aType == wxITEM_CHECK )
218  {
219  #if defined( __WINDOWS__ )
220  item->SetBitmaps( KiBitmap( checked_ok_xpm ), aImage );
221  // A workaround to a strange bug on Windows, wx Widgets 3.0:
222  // size of bitmaps is not taken in account for wxITEM_CHECK menu
223  // unless we call SetFont
224  item->SetFont(*wxNORMAL_FONT);
225  #endif
226  }
227  else
228  item->SetBitmap( aImage );
229  }
230 
231  aMenu->Append( item );
232 
233  return item;
234 }
235 
236 wxMenuItem* AddMenuItem( wxMenu* aMenu, wxMenu* aSubMenu, int aId,
237  const wxString& aText, const wxBitmap& aImage )
238 {
239  wxMenuItem* item;
240 
241  item = new wxMenuItem( aMenu, aId, aText );
242  item->SetSubMenu( aSubMenu );
243 
244  // Retrieve the global applicaton show icon option:
245  bool useImagesInMenus = Pgm().GetUseIconsInMenus();
246 
247  if( useImagesInMenus )
248  item->SetBitmap( aImage );
249 
250  aMenu->Append( item );
251 
252  return item;
253 }
254 
255 
256 wxMenuItem* AddMenuItem( wxMenu* aMenu, wxMenu* aSubMenu, int aId,
257  const wxString& aText, const wxString& aHelpText,
258  const wxBitmap& aImage )
259 {
260  wxMenuItem* item;
261 
262  item = new wxMenuItem( aMenu, aId, aText, aHelpText );
263  item->SetSubMenu( aSubMenu );
264 
265  // Retrieve the global applicaton show icon option:
266  bool useImagesInMenus = Pgm().GetUseIconsInMenus();
267 
268  if( useImagesInMenus )
269  item->SetBitmap( aImage );
270 
271  aMenu->Append( item );
272 
273  return item;
274 }
PNG memory record (file in memory).
Definition: bitmap_types.h:41
wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmap &aImage, wxItemKind aType=wxITEM_NORMAL)
Function AddMenuItem is an inline helper function to create and insert a menu item with an icon into ...
Definition: bitmap.cpp:173
int KiIconScale(wxWindow *aWindow)
Function KiIconScale Returns the automatic scale factor that would be used for a given window by KiSc...
Definition: bitmap.cpp:88
Template specialization to enable wxStrings for certain containers (e.g. unordered_map) ...
Definition: bitmap.cpp:54
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: kicad.cpp:65
wxBitmap KiScaledBitmap(BITMAP_DEF aBitmap, EDA_BASE_FRAME *aWindow)
Function KiScaledBitmap Constructs a wxBitmap from a memory record, scaling it if device DPI demands ...
Definition: bitmap.cpp:114
const unsigned char * png
Definition: bitmap_types.h:43
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Function KiBitmap constructs a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:78
result_type operator()(argument_type const &id) const noexcept
Definition: bitmap.cpp:60
wxBitmap * KiBitmapNew(BITMAP_DEF aBitmap)
Function KiBitmapNew allocates a wxBitmap on heap from a memory record, held in a BITMAP_DEF...
Definition: bitmap.cpp:164
Base window classes and related definitions.
SCALED_BITMAP_ID argument_type
Definition: bitmap.cpp:57
bool GetUseIconsInMenus()
Definition: pgm_base.h:328
BITMAP_DEF bitmap
Definition: bitmap.cpp:44
const int scale
see class PGM_BASE
Class EDA_BASE_FRAME is the base frame for deriving all KiCad main window classes.
Definition: wxstruct.h:117
The common library.
void KiScaledSeparator(wxAuiToolBar *aToolbar, EDA_BASE_FRAME *aWindow)
Function KiScaledSeparator Adds a separator to the given toolbar scaled the same way as KiScaledBitma...
Definition: bitmap.cpp:146
virtual int GetIconScale()
Function GetIconScale.
Definition: wxstruct.h:459
bool operator==(SCALED_BITMAP_ID const &other) const noexcept
Definition: bitmap.cpp:47
static int get_scale_factor(EDA_BASE_FRAME *aWindow)
Definition: bitmap.cpp:103