27 #if defined(__ANDROID__)
29 #include <GL/gl_private.h>
30 #include <GLES2/gl2.h>
32 #elif defined(ocpnUSE_GL)
38 #elif defined(__WXOSX__)
39 #include <OpenGL/gl.h>
40 #include <OpenGL/glu.h>
41 typedef void (* _GLUfuncptr)();
42 #define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
44 #elif defined(__WXQT__) || defined(__WXGTK__)
50 #include <wx/arrstr.h>
51 #include <wx/bitmap.h>
53 #include <wx/filename.h>
54 #include <wx/gdicmn.h>
56 #include <wx/string.h>
59 #include "model/base_platform.h"
60 #include "model/cutil.h"
61 #include "model/MarkIcon.h"
62 #include "model/route_point.h"
64 #include "svg_utils.h"
65 #include "waypointman_gui.h"
69 extern float g_MarkScaleFactorExp;
71 extern bool g_bUserIconsFirst;
74 return (mi1->icon_name.CmpNoCase(mi2->icon_name));
81 msg.Printf(_T(
"DPMM: %g ScaleFactorExp: %g"), displayDPmm,
82 g_MarkScaleFactorExp);
86 wxChar sep = wxFileName::GetPathSeparator();
87 if (UserIconPath.Last() != sep) UserIconPath.Append(sep);
88 UserIconPath.Append(_T(
"UserIcons/"));
90 wxLogMessage(_T(
"Looking for UserIcons at ") + UserIconPath);
92 if (wxDir::Exists(UserIconPath)) {
93 wxLogMessage(_T(
"Loading UserIcons from ") + UserIconPath);
94 wxArrayString FileList;
96 wxBitmap default_bm = wxBitmap(1,1);
99 wxDir::GetAllFiles(UserIconPath, &FileList, _T(
""), wxDIR_FILES);
101 for (
int ifile = 0; ifile < n_files; ifile++) {
102 wxString name = g_bUserIconsFirst ? FileList[n_files - ifile - 1] : FileList[ifile];
105 wxString iconname = fn.GetName();
107 if (fn.GetExt().Lower() == _T(
"xpm")) {
108 if (icon1.LoadFile(name, wxBITMAP_TYPE_XPM)) {
109 wxLogMessage(_T(
"Adding icon: ") + iconname);
110 wxImage image = icon1.ConvertToImage();
111 ProcessIcon(image, iconname, iconname, g_bUserIconsFirst);
114 if (fn.GetExt().Lower() == _T(
"png")) {
115 if (icon1.LoadFile(name, wxBITMAP_TYPE_PNG)) {
116 wxLogMessage(_T(
"Adding icon: ") + iconname);
117 wxImage image = icon1.ConvertToImage();
118 ProcessIcon(image, iconname, iconname, g_bUserIconsFirst);
121 if (fn.GetExt().Lower() == _T(
"svg")) {
123 SVGDocumentPixelSize(name, w, h);
127 double bm_size_nom = wxMin(wxMax(w,h), floor(displayDPmm * 20));
129 bm_size_nom = wxMax(bm_size_nom, 15);
131 bm_size_nom /= OCPN_GetWinDIPScaleFactor();
132 bm_size_nom *= g_MarkScaleFactorExp;
135 double aspect = h / w;
138 if (fabs(aspect - 1.0) > .05) {
140 LoadSVG(name, (
int)bm_size_nom,
142 &default_bm).ConvertToImage();
145 wxRect rClip = CropImageOnAlpha(image);
146 wxImage imageClip = image.GetSubImage(rClip);
147 imageClip.Rescale(bm_size_nom, bm_size_nom / aspect,
148 wxIMAGE_QUALITY_BICUBIC);
149 pmi = ProcessIcon(imageClip, iconname, iconname, g_bUserIconsFirst);
153 const unsigned int bm_size = bm_size_nom;
154 wxImage iconSVG = LoadSVG(name, bm_size, bm_size,
155 &default_bm,
false).ConvertToImage();
156 wxRect rClip = CropImageOnAlpha(iconSVG);
157 wxImage imageClip = iconSVG.GetSubImage(rClip);
158 pmi = ProcessIcon(iconSVG, iconname, iconname, g_bUserIconsFirst);
161 if (pmi) pmi->preScaled =
true;
167 MarkIcon* WayPointmanGui::ProcessIcon(wxImage image,
const wxString& key,
168 const wxString& description,
bool add_in_front) {
174 for (
unsigned int i = 0; i < m_waypoint_man.m_pIconArray->GetCount(); i++) {
175 pmi = (
MarkIcon *)m_waypoint_man.m_pIconArray->Item(i);
176 if (pmi->icon_name.IsSameAs(key)) {
178 delete pmi->piconBitmap;
185 pmi->icon_name = key;
187 m_waypoint_man.m_pIconArray->Insert(pmi, 0);
189 m_waypoint_man.m_pIconArray->Add(pmi);
194 wxBitmap *pbm =
new wxBitmap(image);
195 pmi->icon_name = key;
196 pmi->icon_description = description;
197 pmi->piconBitmap = NULL;
198 pmi->icon_texture = 0;
199 pmi->preScaled =
false;
200 pmi->iconImage = pbm->ConvertToImage();
201 pmi->m_blistImageOK =
false;
207 void WayPointmanGui::ProcessIcons(
ocpnStyle::Style *style,
double displayDPmm) {
208 for (
unsigned int i = 0; i < m_waypoint_man.m_pIconArray->GetCount(); i++) {
210 delete pmi->piconBitmap;
213 m_waypoint_man.m_pIconArray->Clear();
215 ProcessDefaultIcons(displayDPmm);
221 ProcessUserIcons(style, displayDPmm);
223 if (NULL != m_waypoint_man.pmarkicon_image_list) {
224 m_waypoint_man.pmarkicon_image_list->RemoveAll();
225 delete m_waypoint_man.pmarkicon_image_list;
226 m_waypoint_man.pmarkicon_image_list = NULL;
234 for (
unsigned int i = 0; i < m_waypoint_man.m_pIconArray->GetCount(); i++) {
236 w = wxMax(w, pmi->iconImage.GetWidth());
237 h = wxMax(h, pmi->iconImage.GetHeight());
240 m_waypoint_man.m_bitmapSizeForList = wxMax(w, h);
241 m_waypoint_man.m_bitmapSizeForList =
242 wxMin(100, m_waypoint_man.m_bitmapSizeForList);
245 void WayPointmanGui::ProcessDefaultIcons(
double displayDPmm) {
246 wxString iconDir = g_BasePlatform->GetSharedDataDir();
247 appendOSDirSlash(&iconDir);
248 iconDir.append(_T(
"uidata"));
249 appendOSDirSlash(&iconDir);
250 iconDir.append(_T(
"markicons"));
251 appendOSDirSlash(&iconDir);
256 if (m_waypoint_man.m_pLegacyIconArray)
257 m_waypoint_man.m_pLegacyIconArray->Clear();
259 m_waypoint_man.m_pLegacyIconArray =
260 new SortedArrayOfMarkIcon(CompareMarkIcons);
262 pmi = ProcessLegacyIcon(iconDir + _T(
"Symbol-Empty.svg"), _T(
"empty"),
263 _T(
"Empty"), displayDPmm);
264 if (pmi) pmi->preScaled =
true;
265 pmi = ProcessLegacyIcon(iconDir + _T(
"Symbol-Triangle.svg"), _T(
"triangle"),
266 _T(
"Triangle"), displayDPmm);
267 if (pmi) pmi->preScaled =
true;
268 pmi = ProcessLegacyIcon(iconDir + _T(
"1st-Active-Waypoint.svg"),
269 _T(
"activepoint"), _T(
"Active WP"), displayDPmm);
270 if (pmi) pmi->preScaled =
true;
271 pmi = ProcessLegacyIcon(iconDir + _T(
"Marks-Boarding-Location.svg"),
272 _T(
"boarding"), _T(
"Boarding Location"), displayDPmm);
273 if (pmi) pmi->preScaled =
true;
274 pmi = ProcessLegacyIcon(iconDir + _T(
"Hazard-Airplane.svg"), _T(
"airplane"),
275 _T(
"Airplane"), displayDPmm);
276 if (pmi) pmi->preScaled =
true;
277 pmi = ProcessLegacyIcon(iconDir + _T(
"1st-Anchorage.svg"), _T(
"anchorage"),
278 _T(
"Anchorage"), displayDPmm);
279 if (pmi) pmi->preScaled =
true;
280 pmi = ProcessLegacyIcon(iconDir + _T(
"Symbol-Anchor2.svg"), _T(
"anchor"),
281 _T(
"Anchor"), displayDPmm);
282 if (pmi) pmi->preScaled =
true;
283 pmi = ProcessLegacyIcon(iconDir + _T(
"Marks-Boundary.svg"), _T(
"boundary"),
284 _T(
"Boundary Mark"), displayDPmm);
285 if (pmi) pmi->preScaled =
true;
286 pmi = ProcessLegacyIcon(iconDir + _T(
"Marks-Buoy-TypeA.svg"), _T(
"bouy1"),
287 _T(
"Bouy Type A"), displayDPmm);
288 if (pmi) pmi->preScaled =
true;
289 pmi = ProcessLegacyIcon(iconDir + _T(
"Marks-Buoy-TypeB.svg"), _T(
"bouy2"),
290 _T(
"Bouy Type B"), displayDPmm);
291 if (pmi) pmi->preScaled =
true;
292 pmi = ProcessLegacyIcon(iconDir + _T(
"Activity-Campfire.svg"), _T(
"campfire"),
293 _T(
"Campfire"), displayDPmm);
294 if (pmi) pmi->preScaled =
true;
295 pmi = ProcessLegacyIcon(iconDir + _T(
"Activity-Camping.svg"), _T(
"camping"),
296 _T(
"Camping Spot"), displayDPmm);
297 if (pmi) pmi->preScaled =
true;
298 pmi = ProcessLegacyIcon(iconDir + _T(
"Sea-Floor-Coral.svg"), _T(
"coral"),
299 _T(
"Coral"), displayDPmm);
300 if (pmi) pmi->preScaled =
true;
301 pmi = ProcessLegacyIcon(iconDir + _T(
"Activity-Fishing.svg"), _T(
"fishhaven"),
302 _T(
"Fish Haven"), displayDPmm);
303 if (pmi) pmi->preScaled =
true;
304 pmi = ProcessLegacyIcon(iconDir + _T(
"Activity-Fishing.svg"), _T(
"fishing"),
305 _T(
"Fishing Spot"), displayDPmm);
306 if (pmi) pmi->preScaled =
true;
307 pmi = ProcessLegacyIcon(iconDir + _T(
"Activity-Fishing.svg"), _T(
"fish"),
308 _T(
"Fish"), displayDPmm);
309 if (pmi) pmi->preScaled =
true;
310 pmi = ProcessLegacyIcon(iconDir + _T(
"Marks-Mooring-Buoy.svg"), _T(
"float"),
311 _T(
"Float"), displayDPmm);
312 if (pmi) pmi->preScaled =
true;
313 pmi = ProcessLegacyIcon(iconDir + _T(
"Service-Food.svg"), _T(
"food"),
314 _T(
"Food"), displayDPmm);
315 if (pmi) pmi->preScaled =
true;
316 pmi = ProcessLegacyIcon(iconDir + _T(
"Service-Fuel-Pump-Diesel-Petrol.svg"),
317 _T(
"fuel"), _T(
"Fuel"), displayDPmm);
318 if (pmi) pmi->preScaled =
true;
319 pmi = ProcessLegacyIcon(iconDir + _T(
"Marks-Light-Green.svg"),
320 _T(
"greenlite"), _T(
"Green Light"), displayDPmm);
321 if (pmi) pmi->preScaled =
true;
322 pmi = ProcessLegacyIcon(iconDir + _T(
"Sea-Floor-Sea-Weed.svg"), _T(
"kelp"),
323 _T(
"Kelp"), displayDPmm);
324 if (pmi) pmi->preScaled =
true;
325 pmi = ProcessLegacyIcon(iconDir + _T(
"Marks-Light-TypeA.svg"), _T(
"light"),
326 _T(
"Light Type A"), displayDPmm);
327 if (pmi) pmi->preScaled =
true;
328 pmi = ProcessLegacyIcon(iconDir + _T(
"Marks-Light-TypeB.svg"), _T(
"light1"),
329 _T(
"Light Type B"), displayDPmm);
330 if (pmi) pmi->preScaled =
true;
331 pmi = ProcessLegacyIcon(iconDir + _T(
"Marks-Light-Vessel.svg"),
332 _T(
"litevessel"), _T(
"litevessel"), displayDPmm);
333 if (pmi) pmi->preScaled =
true;
334 pmi = ProcessLegacyIcon(iconDir + _T(
"1st-Man-Overboard.svg"), _T(
"mob"),
335 _T(
"MOB"), displayDPmm);
336 if (pmi) pmi->preScaled =
true;
337 pmi = ProcessLegacyIcon(iconDir + _T(
"Marks-Mooring-Buoy.svg"), _T(
"mooring"),
338 _T(
"Mooring Bouy"), displayDPmm);
339 if (pmi) pmi->preScaled =
true;
340 pmi = ProcessLegacyIcon(iconDir + _T(
"Marks-Mooring-Buoy-Super.svg"),
341 _T(
"oilbouy"), _T(
"Oil Bouy"), displayDPmm);
342 if (pmi) pmi->preScaled =
true;
343 pmi = ProcessLegacyIcon(iconDir + _T(
"Hazard-Oil-Platform.svg"),
344 _T(
"platform"), _T(
"Platform"), displayDPmm);
345 if (pmi) pmi->preScaled =
true;
346 pmi = ProcessLegacyIcon(iconDir + _T(
"Marks-Light-Red-Green.svg"),
347 _T(
"redgreenlite"), _T(
"Red/Green Light"), displayDPmm);
348 if (pmi) pmi->preScaled =
true;
349 pmi = ProcessLegacyIcon(iconDir + _T(
"Marks-Light-Red.svg"), _T(
"redlite"),
350 _T(
"Red Light"), displayDPmm);
351 if (pmi) pmi->preScaled =
true;
352 pmi = ProcessLegacyIcon(iconDir + _T(
"Hazard-Rock-Exposed.svg"), _T(
"rock1"),
353 _T(
"Rock (exposed)"), displayDPmm);
354 if (pmi) pmi->preScaled =
true;
355 pmi = ProcessLegacyIcon(iconDir + _T(
"Hazard-Rock-Awash.svg"), _T(
"rock2"),
356 _T(
"Rock, (awash)"), displayDPmm);
357 if (pmi) pmi->preScaled =
true;
358 pmi = ProcessLegacyIcon(iconDir + _T(
"Hazard-Sandbar.svg"), _T(
"sand"),
359 _T(
"Sand"), displayDPmm);
360 if (pmi) pmi->preScaled =
true;
361 pmi = ProcessLegacyIcon(iconDir + _T(
"Activity-Diving-Scuba-Flag.svg"),
362 _T(
"scuba"), _T(
"Scuba"), displayDPmm);
363 if (pmi) pmi->preScaled =
true;
364 pmi = ProcessLegacyIcon(iconDir + _T(
"Hazard-Sandbar.svg"), _T(
"shoal"),
365 _T(
"Shoal"), displayDPmm);
366 if (pmi) pmi->preScaled =
true;
367 pmi = ProcessLegacyIcon(iconDir + _T(
"Hazard-Snag.svg"), _T(
"snag"),
368 _T(
"Snag"), displayDPmm);
369 if (pmi) pmi->preScaled =
true;
370 pmi = ProcessLegacyIcon(iconDir + _T(
"Symbol-Square.svg"), _T(
"square"),
371 _T(
"Square"), displayDPmm);
372 if (pmi) pmi->preScaled =
true;
373 pmi = ProcessLegacyIcon(iconDir + _T(
"1st-Diamond.svg"), _T(
"diamond"),
374 _T(
"Diamond"), displayDPmm);
375 if (pmi) pmi->preScaled =
true;
376 pmi = ProcessLegacyIcon(iconDir + _T(
"Symbol-Circle.svg"), _T(
"circle"),
377 _T(
"Circle"), displayDPmm);
378 if (pmi) pmi->preScaled =
true;
379 pmi = ProcessLegacyIcon(iconDir + _T(
"Hazard-Wreck1.svg"), _T(
"wreck1"),
380 _T(
"Wreck A"), displayDPmm);
381 if (pmi) pmi->preScaled =
true;
382 pmi = ProcessLegacyIcon(iconDir + _T(
"Hazard-Wreck2.svg"), _T(
"wreck2"),
383 _T(
"Wreck B"), displayDPmm);
384 if (pmi) pmi->preScaled =
true;
385 pmi = ProcessLegacyIcon(iconDir + _T(
"Symbol-X-Small-Blue.svg"), _T(
"xmblue"),
386 _T(
"Blue X"), displayDPmm);
387 if (pmi) pmi->preScaled =
true;
388 pmi = ProcessLegacyIcon(iconDir + _T(
"Symbol-X-Small-Green.svg"),
389 _T(
"xmgreen"), _T(
"Green X"), displayDPmm);
390 if (pmi) pmi->preScaled =
true;
391 pmi = ProcessLegacyIcon(iconDir + _T(
"Symbol-X-Small-Red.svg"), _T(
"xmred"),
392 _T(
"Red X"), displayDPmm);
393 if (pmi) pmi->preScaled =
true;
396 if (m_waypoint_man.m_pExtendedIconArray) {
397 m_waypoint_man.m_pExtendedIconArray->Clear();
399 m_waypoint_man.m_pExtendedIconArray =
400 new SortedArrayOfMarkIcon(CompareMarkIcons);
404 wxArrayString FileList;
407 int n_files = wxDir::GetAllFiles( iconDir, &FileList );
411 if( fabs(g_ChartScaleFactorExp - 1.0) > 0.1){
413 for(
int ifile = 0; ifile < n_files; ifile++ ) {
414 wxString name = FileList[ifile];
416 wxFileName fn( name );
418 if( fn.GetExt().Lower() == _T(
"svg") ) {
419 wxBitmap bmt = LoadSVG(name, -1, -1 );
420 bm_size = bmt.GetWidth() * g_ChartScaleFactorExp;
426 for(
int ifile = 0; ifile < n_files; ifile++ ) {
427 wxString name = FileList[ifile];
429 wxFileName fn( name );
430 wxString iconname = fn.GetName();
432 if( fn.GetExt().Lower() == _T(
"svg") ) {
433 wxImage iconSVG = LoadSVG( name, (
int)bm_size, (
int)bm_size );
434 MarkIcon * pmi = ProcessExtendedIcon( iconSVG, iconname, iconname );
436 pmi->preScaled =
true;
441 wxArrayString FileList;
443 double bm_size = wxMax(4.0, floor(displayDPmm * 12.0));
444 bm_size /= OCPN_GetWinDIPScaleFactor();
445 bm_size *= g_MarkScaleFactorExp;
447 int n_files = wxDir::GetAllFiles(iconDir, &FileList);
449 g_BasePlatform->ShowBusySpinner();
451 for (
int ifile = 0; ifile < n_files; ifile++) {
452 wxString name = FileList[ifile];
455 wxString iconname = fn.GetName();
458 if (fn.GetExt().Lower() == _T(
"svg")) {
461 SVGDocumentPixelSize(name, w, h);
464 w = wxMax(wxMax(w, h), 15);
465 bm_size = w * g_MarkScaleFactorExp;
466 bm_size /= OCPN_GetWinDIPScaleFactor();
468 wxBitmap bmp = LoadSVG(name, (
int)bm_size, (
int)bm_size);
470 wxImage iconSVG = bmp.ConvertToImage();
472 MarkIcon *pmi = ProcessExtendedIcon(iconSVG, iconname, iconname);
473 if (pmi) pmi->preScaled =
true;
475 wxLogMessage(
"Failed loading mark icon " + name);
479 g_BasePlatform->HideBusySpinner();
484 auto size = m_waypoint_man.m_pLegacyIconArray->GetCount();
485 for (
unsigned int i = 0; i < size; i++) {
486 pmi = (
MarkIcon *)m_waypoint_man.m_pLegacyIconArray->Item(i);
487 m_waypoint_man.m_pIconArray->Add(pmi);
490 size = m_waypoint_man.m_pExtendedIconArray->GetCount();
491 for (
unsigned int i = 0; i < size; i++) {
492 pmi = (
MarkIcon *) m_waypoint_man.m_pExtendedIconArray->Item(i);
497 auto legacy_count = m_waypoint_man.m_pLegacyIconArray->GetCount();
498 for (
unsigned int j = 0; j < legacy_count; j++) {
500 (
MarkIcon *)m_waypoint_man.m_pLegacyIconArray->Item(j);
501 if (pmiLegacy->icon_name.IsSameAs(pmi->icon_name)) {
506 if (!noAdd) m_waypoint_man.m_pIconArray->Add(pmi);
510 void WayPointmanGui::ReloadAllIcons(
double displayDPmm) {
511 ProcessIcons(g_StyleManager->GetCurrentStyle(), displayDPmm);
513 for (
unsigned int i = 0; i < m_waypoint_man.m_pIconArray->GetCount(); i++) {
516 if (m_waypoint_man.m_cs == GLOBAL_COLOR_SCHEME_DUSK) {
517 dim_image = m_waypoint_man.CreateDimImage(pmi->iconImage, .50);
518 pmi->iconImage = dim_image;
519 }
else if (m_waypoint_man.m_cs == GLOBAL_COLOR_SCHEME_NIGHT) {
520 dim_image = m_waypoint_man.CreateDimImage(pmi->iconImage, .20);
521 pmi->iconImage = dim_image;
524 ReloadRoutepointIcons();
527 void WayPointmanGui::SetColorScheme(ColorScheme cs,
double displayDPmm) {
528 m_waypoint_man.m_cs = cs;
529 ReloadAllIcons(displayDPmm);
532 MarkIcon *WayPointmanGui::ProcessLegacyIcon(wxString fileName,
const wxString &key,
533 const wxString &description,
534 double displayDPmm) {
535 double bm_size = -1.0;
537 #ifndef ocpnUSE_wxBitmapBundle
539 if (fabs(g_MarkScaleFactorExp - 1.0) > 0.1) {
540 wxBitmap img = LoadSVG(fileName, -1, -1);
541 bm_size = img.GetWidth() * g_MarkScaleFactorExp;
542 bm_size /= OCPN_GetWinDIPScaleFactor();
551 float nominal_legacy_icon_size_pixels = wxMax(4.0,
552 floor(displayDPmm * 12.0));
554 float pix_factor = nominal_legacy_icon_size_pixels / 68.0;
557 SVGDocumentPixelSize(fileName, w, h);
559 bm_size = w * pix_factor * g_MarkScaleFactorExp;
564 SVGDocumentPixelSize(fileName, w, h);
565 w = wxMax(wxMax(w, h), 15);
567 bm_size = w * g_MarkScaleFactorExp;
568 bm_size /= OCPN_GetWinDIPScaleFactor();
571 wxBitmap bm = LoadSVG(fileName, (
int)bm_size, (
int)bm_size);
576 LoadSVG(fileName, (
int)bm_size, (
int)bm_size).ConvertToImage();
578 wxRect rClip = CropImageOnAlpha(image);
579 wxImage imageClip = image.GetSubImage(rClip);
586 for (
unsigned int i = 0; i < m_waypoint_man.m_pLegacyIconArray->GetCount(); i++) {
587 pmi = (
MarkIcon *)m_waypoint_man.m_pLegacyIconArray->Item(i);
588 if (pmi->icon_name.IsSameAs(key)) {
590 delete pmi->piconBitmap;
597 pmi->icon_name = key;
598 m_waypoint_man.m_pLegacyIconArray->Add(pmi);
601 pmi->icon_name = key;
602 pmi->icon_description = description;
603 pmi->piconBitmap = NULL;
604 pmi->icon_texture = 0;
605 pmi->preScaled =
false;
606 pmi->iconImage = imageClip;
607 pmi->m_blistImageOK =
false;
612 MarkIcon *WayPointmanGui::ProcessExtendedIcon(wxImage &image,
614 const wxString &description) {
620 auto size = m_waypoint_man.m_pExtendedIconArray->GetCount();
621 for (
unsigned int i = 0; i < size; i++) {
622 pmi = (
MarkIcon *)m_waypoint_man.m_pExtendedIconArray->Item(i);
623 if (pmi->icon_name.IsSameAs(key)) {
625 delete pmi->piconBitmap;
632 pmi->icon_name = key;
633 m_waypoint_man.m_pExtendedIconArray->Add(pmi);
636 wxRect rClip = CropImageOnAlpha(image);
637 wxImage imageClip = image.GetSubImage(rClip);
639 pmi->icon_name = key;
640 pmi->icon_description = description;
641 pmi->piconBitmap =
new wxBitmap(imageClip);
642 pmi->icon_texture = 0;
643 pmi->preScaled =
false;
644 pmi->iconImage = imageClip;
645 pmi->m_blistImageOK =
false;
650 wxRect WayPointmanGui::CropImageOnAlpha(wxImage &image) {
651 const int w = image.GetWidth();
652 const int h = image.GetHeight();
654 wxRect rv = wxRect(0, 0, w, h);
655 if (!image.HasAlpha())
return rv;
657 unsigned char *pAlpha = image.GetAlpha();
665 for (
int i = 0; i < h; i++) {
666 int lineStartIndex = i * w;
669 while ((j < w) && (pAlpha[lineStartIndex + j] == 0)) j++;
670 leftCrop = wxMin(leftCrop, j);
673 while (k && (pAlpha[lineStartIndex + k] == 0)) k--;
674 rightCrop = wxMin(rightCrop, image.GetWidth() - k - 2);
678 for (
int i = 0; i < w; i++) {
679 int columnStartIndex = i;
682 while ((j < h) && (pAlpha[columnStartIndex + (j * w)] == 0)) j++;
683 topCrop = wxMin(topCrop, j);
686 while (k && (pAlpha[columnStartIndex + (k * w)] == 0)) k--;
687 bottomCrop = wxMin(bottomCrop, h - k - 2);
690 int xcrop = wxMin(rightCrop, leftCrop);
691 int ycrop = wxMin(topCrop, bottomCrop);
692 int crop = wxMin(xcrop, ycrop);
694 rv.x = wxMax(crop, 0);
695 rv.width = wxMax(1, w - (2 * crop));
696 rv.width = wxMin(rv.width, w);
698 rv.height = rv.width;
703 void WayPointmanGui::ReloadRoutepointIcons() {
706 wxRoutePointListNode *node = m_waypoint_man.m_pWayPointList->GetFirst();
710 node = node->GetNext();
714 unsigned int WayPointmanGui::GetIconTexture(
const wxBitmap *pbm,
int &glw,
717 int index = m_waypoint_man.GetIconIndex(pbm);
720 if (!pmi->icon_texture) {
722 wxImage image = pbm->ConvertToImage();
723 unsigned char *d = image.GetData();
729 glGenTextures(1, &pmi->icon_texture);
730 glBindTexture(GL_TEXTURE_2D, pmi->icon_texture);
732 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
733 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
734 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
736 int w = image.GetWidth(), h = image.GetHeight();
738 pmi->tex_w = NextPow2(w);
739 pmi->tex_h = NextPow2(h);
741 unsigned char *a = image.GetAlpha();
743 unsigned char mr, mg, mb;
744 if (!a) image.GetOrFindMaskColour(&mr, &mg, &mb);
746 unsigned char *e =
new unsigned char[4 * w * h];
747 for (
int y = 0; y < h; y++) {
748 for (
int x = 0; x < w; x++) {
749 unsigned char r, g, b;
750 int off = (y * w + x);
759 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
763 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pmi->tex_w, pmi->tex_h, 0, GL_RGBA,
764 GL_UNSIGNED_BYTE, NULL);
765 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, e);
773 return pmi->icon_texture;