27#if defined(__ANDROID__)
29#include <GL/gl_private.h>
32#elif defined(ocpnUSE_GL)
38#elif defined(__WXOSX__)
40#include <OpenGL/glu.h>
41typedef void (*_GLUfuncptr)();
42#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
44#elif defined(__WXQT__) || defined(__WXGTK__)
53#include <wx/filename.h>
59#include "model/base_platform.h"
60#include "model/cutil.h"
61#include "model/MarkIcon.h"
62#include "model/route_point.h"
65#include "waypointman_gui.h"
69extern float g_MarkScaleFactorExp;
71extern bool g_bUserIconsFirst;
74 return (mi1->icon_name.CmpNoCase(mi2->icon_name));
80 msg.Printf(
"DPMM: %g ScaleFactorExp: %g", displayDPmm,
81 g_MarkScaleFactorExp);
85 wxChar sep = wxFileName::GetPathSeparator();
86 if (UserIconPath.Last() != sep) UserIconPath.Append(sep);
87 UserIconPath.Append(
"UserIcons/");
89 wxLogMessage(
"Looking for UserIcons at " + UserIconPath);
91 if (wxDir::Exists(UserIconPath)) {
92 wxLogMessage(
"Loading UserIcons from " + UserIconPath);
93 wxArrayString FileList;
95 wxBitmap default_bm = wxBitmap(1, 1);
97 int n_files = wxDir::GetAllFiles(UserIconPath, &FileList,
"", wxDIR_FILES);
99 for (
int ifile = 0; ifile < n_files; ifile++) {
101 g_bUserIconsFirst ? FileList[n_files - ifile - 1] : FileList[ifile];
104 wxString iconname = fn.GetName();
106 if (fn.GetExt().Lower() ==
"xpm") {
107 if (icon1.LoadFile(name, wxBITMAP_TYPE_XPM)) {
108 wxLogMessage(
"Adding icon: " + iconname);
109 wxImage image = icon1.ConvertToImage();
110 ProcessIcon(image, iconname, iconname, g_bUserIconsFirst);
113 if (fn.GetExt().Lower() ==
"png") {
114 if (icon1.LoadFile(name, wxBITMAP_TYPE_PNG)) {
115 wxLogMessage(
"Adding icon: " + iconname);
116 wxImage image = icon1.ConvertToImage();
117 ProcessIcon(image, iconname, iconname, g_bUserIconsFirst);
120 if (fn.GetExt().Lower() ==
"svg") {
122 SVGDocumentPixelSize(name, w, h);
126 double bm_size_nom = wxMin(wxMax(w, h), floor(displayDPmm * 20));
128 bm_size_nom = wxMax(bm_size_nom, 15);
131 bm_size_nom *= g_MarkScaleFactorExp;
136 if (w != 0 && h != 0) {
141 if (fabs(aspect - 1.0) > .05) {
143 LoadSVG(name, (
int)bm_size_nom, (
int)bm_size_nom, &default_bm)
147 wxRect rClip = CropImageOnAlpha(image);
148 wxImage imageClip = image.GetSubImage(rClip);
149 imageClip.Rescale(bm_size_nom, bm_size_nom / aspect,
150 wxIMAGE_QUALITY_BICUBIC);
151 pmi = ProcessIcon(imageClip, iconname, iconname, g_bUserIconsFirst);
154 const unsigned int bm_size = bm_size_nom;
155 wxImage iconSVG = LoadSVG(name, bm_size, bm_size, &default_bm,
false)
157 wxRect rClip = CropImageOnAlpha(iconSVG);
158 wxImage imageClip = iconSVG.GetSubImage(rClip);
159 pmi = ProcessIcon(iconSVG, iconname, iconname, g_bUserIconsFirst);
162 if (pmi) pmi->preScaled =
true;
168MarkIcon *WayPointmanGui::ProcessIcon(wxImage image,
const wxString &key,
169 const wxString &description,
176 for (
unsigned int i = 0; i < m_waypoint_man.m_pIconArray->GetCount(); i++) {
177 pmi = (
MarkIcon *)m_waypoint_man.m_pIconArray->Item(i);
178 if (pmi->icon_name.IsSameAs(key)) {
180 delete pmi->piconBitmap;
187 pmi->icon_name = key;
189 m_waypoint_man.m_pIconArray->Insert(pmi, 0);
191 m_waypoint_man.m_pIconArray->Add(pmi);
195 wxBitmap *pbm =
new wxBitmap(image);
196 pmi->icon_name = key;
197 pmi->icon_description = description;
198 pmi->piconBitmap = NULL;
199 pmi->icon_texture = 0;
200 pmi->preScaled =
false;
201 pmi->iconImage = pbm->ConvertToImage();
202 pmi->m_blistImageOK =
false;
208void WayPointmanGui::ProcessIcons(
ocpnStyle::Style *style,
double displayDPmm) {
209 for (
unsigned int i = 0; i < m_waypoint_man.m_pIconArray->GetCount(); i++) {
211 delete pmi->piconBitmap;
214 m_waypoint_man.m_pIconArray->Clear();
216 ProcessDefaultIcons(displayDPmm);
222 ProcessUserIcons(style, displayDPmm);
224 if (NULL != m_waypoint_man.pmarkicon_image_list) {
225 m_waypoint_man.pmarkicon_image_list->RemoveAll();
226 delete m_waypoint_man.pmarkicon_image_list;
227 m_waypoint_man.pmarkicon_image_list = NULL;
235 for (
unsigned int i = 0; i < m_waypoint_man.m_pIconArray->GetCount(); i++) {
237 w = wxMax(w, pmi->iconImage.GetWidth());
238 h = wxMax(h, pmi->iconImage.GetHeight());
241 m_waypoint_man.m_bitmapSizeForList = wxMax(w, h);
242 m_waypoint_man.m_bitmapSizeForList =
243 wxMin(100, m_waypoint_man.m_bitmapSizeForList);
246void WayPointmanGui::ProcessDefaultIcons(
double displayDPmm) {
247 wxString iconDir = g_BasePlatform->GetSharedDataDir();
248 appendOSDirSlash(&iconDir);
249 iconDir.append(
"uidata");
250 appendOSDirSlash(&iconDir);
251 iconDir.append(
"markicons");
252 appendOSDirSlash(&iconDir);
257 if (m_waypoint_man.m_pLegacyIconArray)
258 m_waypoint_man.m_pLegacyIconArray->Clear();
260 m_waypoint_man.m_pLegacyIconArray =
261 new SortedArrayOfMarkIcon(CompareMarkIcons);
263 pmi = ProcessLegacyIcon(iconDir +
"Symbol-Empty.svg",
"empty",
"Empty",
265 if (pmi) pmi->preScaled =
true;
266 pmi = ProcessLegacyIcon(iconDir +
"Symbol-Triangle.svg",
"triangle",
267 "Triangle", displayDPmm);
268 if (pmi) pmi->preScaled =
true;
269 pmi = ProcessLegacyIcon(iconDir +
"1st-Active-Waypoint.svg",
"activepoint",
270 "Active WP", displayDPmm);
271 if (pmi) pmi->preScaled =
true;
272 pmi = ProcessLegacyIcon(iconDir +
"Marks-Boarding-Location.svg",
"boarding",
273 "Boarding Location", displayDPmm);
274 if (pmi) pmi->preScaled =
true;
275 pmi = ProcessLegacyIcon(iconDir +
"Hazard-Airplane.svg",
"airplane",
276 "Airplane", displayDPmm);
277 if (pmi) pmi->preScaled =
true;
278 pmi = ProcessLegacyIcon(iconDir +
"1st-Anchorage.svg",
"anchorage",
279 "Anchorage", displayDPmm);
280 if (pmi) pmi->preScaled =
true;
281 pmi = ProcessLegacyIcon(iconDir +
"Symbol-Anchor2.svg",
"anchor",
"Anchor",
283 if (pmi) pmi->preScaled =
true;
284 pmi = ProcessLegacyIcon(iconDir +
"Marks-Boundary.svg",
"boundary",
285 "Boundary Mark", displayDPmm);
286 if (pmi) pmi->preScaled =
true;
287 pmi = ProcessLegacyIcon(iconDir +
"Marks-Buoy-TypeA.svg",
"buoy1",
288 "buoy Type A", displayDPmm);
289 if (pmi) pmi->preScaled =
true;
290 pmi = ProcessLegacyIcon(iconDir +
"Marks-Buoy-TypeB.svg",
"buoy2",
291 "buoy Type B", displayDPmm);
292 if (pmi) pmi->preScaled =
true;
293 pmi = ProcessLegacyIcon(iconDir +
"Activity-Campfire.svg",
"campfire",
294 "Campfire", displayDPmm);
295 if (pmi) pmi->preScaled =
true;
296 pmi = ProcessLegacyIcon(iconDir +
"Activity-Camping.svg",
"camping",
297 "Camping Spot", displayDPmm);
298 if (pmi) pmi->preScaled =
true;
299 pmi = ProcessLegacyIcon(iconDir +
"Sea-Floor-Coral.svg",
"coral",
"Coral",
301 if (pmi) pmi->preScaled =
true;
302 pmi = ProcessLegacyIcon(iconDir +
"Activity-Fishing.svg",
"fishhaven",
303 "Fish Haven", displayDPmm);
304 if (pmi) pmi->preScaled =
true;
305 pmi = ProcessLegacyIcon(iconDir +
"Activity-Fishing.svg",
"fishing",
306 "Fishing Spot", displayDPmm);
307 if (pmi) pmi->preScaled =
true;
308 pmi = ProcessLegacyIcon(iconDir +
"Activity-Fishing.svg",
"fish",
"Fish",
310 if (pmi) pmi->preScaled =
true;
311 pmi = ProcessLegacyIcon(iconDir +
"Marks-Mooring-Buoy.svg",
"float",
"Float",
313 if (pmi) pmi->preScaled =
true;
314 pmi = ProcessLegacyIcon(iconDir +
"Service-Food.svg",
"food",
"Food",
316 if (pmi) pmi->preScaled =
true;
317 pmi = ProcessLegacyIcon(iconDir +
"Service-Fuel-Pump-Diesel-Petrol.svg",
318 "fuel",
"Fuel", displayDPmm);
319 if (pmi) pmi->preScaled =
true;
320 pmi = ProcessLegacyIcon(iconDir +
"Marks-Light-Green.svg",
"greenlite",
321 "Green Light", displayDPmm);
322 if (pmi) pmi->preScaled =
true;
323 pmi = ProcessLegacyIcon(iconDir +
"Sea-Floor-Sea-Weed.svg",
"kelp",
"Kelp",
325 if (pmi) pmi->preScaled =
true;
326 pmi = ProcessLegacyIcon(iconDir +
"Marks-Light-TypeA.svg",
"light",
327 "Light Type A", displayDPmm);
328 if (pmi) pmi->preScaled =
true;
329 pmi = ProcessLegacyIcon(iconDir +
"Marks-Light-TypeB.svg",
"light1",
330 "Light Type B", displayDPmm);
331 if (pmi) pmi->preScaled =
true;
332 pmi = ProcessLegacyIcon(iconDir +
"Marks-Light-Vessel.svg",
"litevessel",
333 "litevessel", displayDPmm);
334 if (pmi) pmi->preScaled =
true;
335 pmi = ProcessLegacyIcon(iconDir +
"1st-Man-Overboard.svg",
"mob",
"MOB",
337 if (pmi) pmi->preScaled =
true;
338 pmi = ProcessLegacyIcon(iconDir +
"Marks-Mooring-Buoy.svg",
"mooring",
339 "Mooring buoy", displayDPmm);
340 if (pmi) pmi->preScaled =
true;
341 pmi = ProcessLegacyIcon(iconDir +
"Marks-Mooring-Buoy-Super.svg",
"oilbuoy",
342 "Oil buoy", displayDPmm);
343 if (pmi) pmi->preScaled =
true;
344 pmi = ProcessLegacyIcon(iconDir +
"Hazard-Oil-Platform.svg",
"platform",
345 "Platform", displayDPmm);
346 if (pmi) pmi->preScaled =
true;
347 pmi = ProcessLegacyIcon(iconDir +
"Marks-Light-Red-Green.svg",
"redgreenlite",
348 "Red/Green Light", displayDPmm);
349 if (pmi) pmi->preScaled =
true;
350 pmi = ProcessLegacyIcon(iconDir +
"Marks-Light-Red.svg",
"redlite",
351 "Red Light", displayDPmm);
352 if (pmi) pmi->preScaled =
true;
353 pmi = ProcessLegacyIcon(iconDir +
"Hazard-Rock-Exposed.svg",
"rock1",
354 "Rock (exposed)", displayDPmm);
355 if (pmi) pmi->preScaled =
true;
356 pmi = ProcessLegacyIcon(iconDir +
"Hazard-Rock-Awash.svg",
"rock2",
357 "Rock, (awash)", displayDPmm);
358 if (pmi) pmi->preScaled =
true;
359 pmi = ProcessLegacyIcon(iconDir +
"Hazard-Sandbar.svg",
"sand",
"Sand",
361 if (pmi) pmi->preScaled =
true;
362 pmi = ProcessLegacyIcon(iconDir +
"Activity-Diving-Scuba-Flag.svg",
"scuba",
363 "Scuba", displayDPmm);
364 if (pmi) pmi->preScaled =
true;
365 pmi = ProcessLegacyIcon(iconDir +
"Hazard-Sandbar.svg",
"shoal",
"Shoal",
367 if (pmi) pmi->preScaled =
true;
368 pmi = ProcessLegacyIcon(iconDir +
"Hazard-Snag.svg",
"snag",
"Snag",
370 if (pmi) pmi->preScaled =
true;
371 pmi = ProcessLegacyIcon(iconDir +
"Symbol-Square.svg",
"square",
"Square",
373 if (pmi) pmi->preScaled =
true;
374 pmi = ProcessLegacyIcon(iconDir +
"1st-Diamond.svg",
"diamond",
"Diamond",
376 if (pmi) pmi->preScaled =
true;
377 pmi = ProcessLegacyIcon(iconDir +
"Symbol-Circle.svg",
"circle",
"Circle",
379 if (pmi) pmi->preScaled =
true;
380 pmi = ProcessLegacyIcon(iconDir +
"Hazard-Wreck1.svg",
"wreck1",
"Wreck A",
382 if (pmi) pmi->preScaled =
true;
383 pmi = ProcessLegacyIcon(iconDir +
"Hazard-Wreck2.svg",
"wreck2",
"Wreck B",
385 if (pmi) pmi->preScaled =
true;
386 pmi = ProcessLegacyIcon(iconDir +
"Symbol-X-Small-Blue.svg",
"xmblue",
387 "Blue X", displayDPmm);
388 if (pmi) pmi->preScaled =
true;
389 pmi = ProcessLegacyIcon(iconDir +
"Symbol-X-Small-Green.svg",
"xmgreen",
390 "Green X", displayDPmm);
391 if (pmi) pmi->preScaled =
true;
392 pmi = ProcessLegacyIcon(iconDir +
"Symbol-X-Small-Red.svg",
"xmred",
"Red X",
394 if (pmi) pmi->preScaled =
true;
397 if (m_waypoint_man.m_pExtendedIconArray) {
398 m_waypoint_man.m_pExtendedIconArray->Clear();
400 m_waypoint_man.m_pExtendedIconArray =
401 new SortedArrayOfMarkIcon(CompareMarkIcons);
405 wxArrayString FileList;
408 int n_files = wxDir::GetAllFiles( iconDir, &FileList );
412 if( fabs(g_ChartScaleFactorExp - 1.0) > 0.1){
414 for(
int ifile = 0; ifile < n_files; ifile++ ) {
415 wxString name = FileList[ifile];
417 wxFileName fn( name );
419 if( fn.GetExt().Lower() ==
"svg" ) {
420 wxBitmap bmt = LoadSVG(name, -1, -1 );
421 bm_size = bmt.GetWidth() * g_ChartScaleFactorExp;
427 for(
int ifile = 0; ifile < n_files; ifile++ ) {
428 wxString name = FileList[ifile];
430 wxFileName fn( name );
431 wxString iconname = fn.GetName();
433 if( fn.GetExt().Lower() ==
"svg" ) {
434 wxImage iconSVG = LoadSVG( name, (
int)bm_size, (
int)bm_size );
435 MarkIcon * pmi = ProcessExtendedIcon( iconSVG, iconname, iconname );
437 pmi->preScaled =
true;
442 wxArrayString FileList;
444 double bm_size = wxMax(4.0, floor(displayDPmm * 12.0));
446 bm_size *= g_MarkScaleFactorExp;
448 int n_files = wxDir::GetAllFiles(iconDir, &FileList);
450 g_BasePlatform->ShowBusySpinner();
452 for (
int ifile = 0; ifile < n_files; ifile++) {
453 wxString name = FileList[ifile];
456 wxString iconname = fn.GetName();
459 if (fn.GetExt().Lower() ==
"svg") {
462 SVGDocumentPixelSize(name, w, h);
465 w = wxMax(wxMax(w, h), 15);
466 bm_size = w * g_MarkScaleFactorExp;
475 float nominal_legacy_icon_size_pixels =
476 wxMax(4.0, floor(displayDPmm * 12.0));
478 float pix_factor = nominal_legacy_icon_size_pixels / 68.0;
479 bm_size *= pix_factor;
482 wxBitmap bmp = LoadSVG(name, (
int)bm_size, (
int)bm_size);
484 wxImage iconSVG = bmp.ConvertToImage();
486 MarkIcon *pmi = ProcessExtendedIcon(iconSVG, iconname, iconname);
487 if (pmi) pmi->preScaled =
true;
489 wxLogMessage(
"Failed loading mark icon " + name);
493 g_BasePlatform->HideBusySpinner();
498 auto size = m_waypoint_man.m_pLegacyIconArray->GetCount();
499 for (
unsigned int i = 0; i < size; i++) {
500 pmi = (
MarkIcon *)m_waypoint_man.m_pLegacyIconArray->Item(i);
501 m_waypoint_man.m_pIconArray->Add(pmi);
504 size = m_waypoint_man.m_pExtendedIconArray->GetCount();
505 for (
unsigned int i = 0; i < size; i++) {
506 pmi = (
MarkIcon *)m_waypoint_man.m_pExtendedIconArray->Item(i);
511 auto legacy_count = m_waypoint_man.m_pLegacyIconArray->GetCount();
512 for (
unsigned int j = 0; j < legacy_count; j++) {
514 (
MarkIcon *)m_waypoint_man.m_pLegacyIconArray->Item(j);
515 if (pmiLegacy->icon_name.IsSameAs(pmi->icon_name)) {
520 if (!noAdd) m_waypoint_man.m_pIconArray->Add(pmi);
524void WayPointmanGui::ReloadAllIcons(
double displayDPmm) {
525 ProcessIcons(g_StyleManager->GetCurrentStyle(), displayDPmm);
527 for (
unsigned int i = 0; i < m_waypoint_man.m_pIconArray->GetCount(); i++) {
530 if (m_waypoint_man.m_cs == GLOBAL_COLOR_SCHEME_DUSK) {
531 dim_image = m_waypoint_man.CreateDimImage(pmi->iconImage, .50);
532 pmi->iconImage = dim_image;
533 }
else if (m_waypoint_man.m_cs == GLOBAL_COLOR_SCHEME_NIGHT) {
534 dim_image = m_waypoint_man.CreateDimImage(pmi->iconImage, .20);
535 pmi->iconImage = dim_image;
538 ReloadRoutepointIcons();
541void WayPointmanGui::SetColorScheme(ColorScheme cs,
double displayDPmm) {
542 m_waypoint_man.m_cs = cs;
543 ReloadAllIcons(displayDPmm);
546MarkIcon *WayPointmanGui::ProcessLegacyIcon(wxString fileName,
548 const wxString &description,
549 double displayDPmm) {
550 double bm_size = -1.0;
552#ifndef ocpnUSE_wxBitmapBundle
554 if (fabs(g_MarkScaleFactorExp - 1.0) > 0.1) {
555 wxBitmap img = LoadSVG(fileName, -1, -1);
556 bm_size = img.GetWidth() * g_MarkScaleFactorExp;
566 float nominal_legacy_icon_size_pixels = wxMax(4.0, floor(displayDPmm * 12.0));
568 float pix_factor = nominal_legacy_icon_size_pixels / 68.0;
571 SVGDocumentPixelSize(fileName, w, h);
573 bm_size = w * pix_factor * g_MarkScaleFactorExp;
578 SVGDocumentPixelSize(fileName, w, h);
579 w = wxMax(wxMax(w, h), 15);
581 bm_size = w * g_MarkScaleFactorExp;
585 wxBitmap bm = LoadSVG(fileName, (
int)bm_size, (
int)bm_size);
586 if (!bm.IsOk())
return NULL;
589 LoadSVG(fileName, (
int)bm_size, (
int)bm_size).ConvertToImage();
591 wxRect rClip = CropImageOnAlpha(image);
592 wxImage imageClip = image.GetSubImage(rClip);
599 for (
unsigned int i = 0; i < m_waypoint_man.m_pLegacyIconArray->GetCount();
601 pmi = (
MarkIcon *)m_waypoint_man.m_pLegacyIconArray->Item(i);
602 if (pmi->icon_name.IsSameAs(key)) {
604 delete pmi->piconBitmap;
611 pmi->icon_name = key;
612 m_waypoint_man.m_pLegacyIconArray->Add(pmi);
615 pmi->icon_name = key;
616 pmi->icon_description = description;
617 pmi->piconBitmap = NULL;
618 pmi->icon_texture = 0;
619 pmi->preScaled =
false;
620 pmi->iconImage = imageClip;
621 pmi->m_blistImageOK =
false;
626MarkIcon *WayPointmanGui::ProcessExtendedIcon(wxImage &image,
628 const wxString &description) {
634 auto size = m_waypoint_man.m_pExtendedIconArray->GetCount();
635 for (
unsigned int i = 0; i < size; i++) {
636 pmi = (
MarkIcon *)m_waypoint_man.m_pExtendedIconArray->Item(i);
637 if (pmi->icon_name.IsSameAs(key)) {
639 delete pmi->piconBitmap;
646 pmi->icon_name = key;
647 m_waypoint_man.m_pExtendedIconArray->Add(pmi);
650 wxRect rClip = CropImageOnAlpha(image);
651 wxImage imageClip = image.GetSubImage(rClip);
653 pmi->icon_name = key;
654 pmi->icon_description = description;
655 pmi->piconBitmap =
new wxBitmap(imageClip);
656 pmi->icon_texture = 0;
657 pmi->preScaled =
false;
658 pmi->iconImage = imageClip;
659 pmi->m_blistImageOK =
false;
664wxRect WayPointmanGui::CropImageOnAlpha(wxImage &image) {
665 const int w = image.GetWidth();
666 const int h = image.GetHeight();
668 wxRect rv = wxRect(0, 0, w, h);
669 if (!image.HasAlpha())
return rv;
671 unsigned char *pAlpha = image.GetAlpha();
679 for (
int i = 0; i < h; i++) {
680 int lineStartIndex = i * w;
683 while ((j < w) && (pAlpha[lineStartIndex + j] == 0)) j++;
684 leftCrop = wxMin(leftCrop, j);
687 while (k && (pAlpha[lineStartIndex + k] == 0)) k--;
688 rightCrop = wxMin(rightCrop, image.GetWidth() - k - 2);
692 for (
int i = 0; i < w; i++) {
693 int columnStartIndex = i;
696 while ((j < h) && (pAlpha[columnStartIndex + (j * w)] == 0)) j++;
697 topCrop = wxMin(topCrop, j);
700 while (k && (pAlpha[columnStartIndex + (k * w)] == 0)) k--;
701 bottomCrop = wxMin(bottomCrop, h - k - 2);
704 int xcrop = wxMin(rightCrop, leftCrop);
705 int ycrop = wxMin(topCrop, bottomCrop);
706 int crop = wxMin(xcrop, ycrop);
708 rv.x = wxMax(crop, 0);
709 rv.width = wxMax(1, w - (2 * crop));
710 rv.width = wxMin(rv.width, w);
712 rv.height = rv.width;
717void WayPointmanGui::ReloadRoutepointIcons() {
720 wxRoutePointListNode *node = m_waypoint_man.m_pWayPointList->GetFirst();
724 node = node->GetNext();
728unsigned int WayPointmanGui::GetIconTexture(
const wxBitmap *pbm,
int &glw,
731 int index = m_waypoint_man.GetIconIndex(pbm);
734 if (!pmi->icon_texture) {
736 wxImage image = pbm->ConvertToImage();
737 unsigned char *d = image.GetData();
743 glGenTextures(1, &pmi->icon_texture);
744 glBindTexture(GL_TEXTURE_2D, pmi->icon_texture);
746 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
747 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
748 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
750 int w = image.GetWidth(), h = image.GetHeight();
752 pmi->tex_w = NextPow2(w);
753 pmi->tex_h = NextPow2(h);
755 unsigned char *a = image.GetAlpha();
757 unsigned char mr, mg, mb;
758 if (!a) image.GetOrFindMaskColour(&mr, &mg, &mb);
760 unsigned char *e =
new unsigned char[4 * w * h];
761 for (
int y = 0; y < h; y++) {
762 for (
int x = 0; x < w; x++) {
763 unsigned char r, g, b;
764 int off = (y * w + x);
773 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
777 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pmi->tex_w, pmi->tex_h, 0, GL_RGBA,
778 GL_UNSIGNED_BYTE, NULL);
779 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, e);
787 return pmi->icon_texture;
Represents a waypoint or mark within the navigation system.
PlugIn Object Definition/API.
double OCPN_GetWinDIPScaleFactor()
Gets Windows-specific DPI scaling factor.