29#include "model/comm_vars.h"
31#include "model/own_ship.h"
35#include "glChartCanvas.h"
36#include "ocpn_frame.h"
40#define GL_RGBA8 0x8058
43ocpnCompass::ocpnCompass(
ChartCanvas* parent,
bool bShowGPS) {
45 m_bshowGPS = bShowGPS;
48 _img_compass = style->GetIcon(
"CompassRose");
49 _img_gpsRed = style->GetIcon(
"gpsRed");
53 m_pStatBoxToolStaticBmp = NULL;
56 wxRect(style->GetCompassXOffset(), style->GetCompassYOffset(),
57 _img_compass.GetWidth() + _img_gpsRed.GetWidth() +
58 style->GetCompassLeftMargin() * 2 + style->GetToolSeparation(),
59 _img_compass.GetHeight() + style->GetCompassTopMargin() +
60 style->GetCompassBottomMargin());
68 m_cs = GLOBAL_COLOR_SCHEME_RGB;
71ocpnCompass::~ocpnCompass() {
74 glDeleteTextures(1, &m_texobj);
79 delete m_pStatBoxToolStaticBmp;
82void ocpnCompass::Paint(
ocpnDC& dc) {
83 if (m_shown && m_StatBmp.IsOk()) {
84#if defined(ocpnUSE_GLES) || defined(ocpnUSE_GL)
85 if (g_bopengl && !m_texobj) {
88 glGenTextures(1, &m_texobj);
92 if (g_bopengl && m_texobj ) {
93 glBindTexture(GL_TEXTURE_2D, m_texobj);
94 glEnable(GL_TEXTURE_2D);
96#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
103 uv[2] = (float)m_image_width / m_tex_w;
105 uv[4] = (float)m_image_width / m_tex_w;
106 uv[5] = (float)m_image_height / m_tex_h;
108 uv[7] = (float)m_image_height / m_tex_h;
111 coords[0] = m_rect.x;
112 coords[1] = m_rect.y;
113 coords[2] = m_rect.x + m_rect.width;
114 coords[3] = m_rect.y;
115 coords[4] = m_rect.x + m_rect.width;
116 coords[5] = m_rect.y + m_rect.height;
117 coords[6] = m_rect.x;
118 coords[7] = m_rect.y + m_rect.height;
120 m_parent->GetglCanvas()->RenderTextures(dc, coords, uv, 4,
127 glVertex2i(m_rect.x, m_rect.y);
128 glTexCoord2f((
float)m_image_width / m_tex_w, 0);
129 glVertex2i(m_rect.x + m_rect.width, m_rect.y);
130 glTexCoord2f((
float)m_image_width / m_tex_w,
131 (
float)m_image_height / m_tex_h);
132 glVertex2i(m_rect.x + m_rect.width, m_rect.y + m_rect.height);
133 glTexCoord2f(0, (
float)m_image_height / m_tex_h);
134 glVertex2i(m_rect.x, m_rect.y + m_rect.height);
139 glDisable(GL_TEXTURE_2D);
145 double scale = m_parent->GetContentScaleFactor();
147 wxImage image = m_StatBmp.ConvertToImage();
148 image.Rescale(image.GetWidth() *
scale, image.GetHeight() *
scale);
150 dc.DrawBitmap(bmp, m_rect.x, m_rect.y,
true);
152 dc.DrawBitmap(m_StatBmp, m_rect.x, m_rect.y,
true);
154 dc.DrawBitmap(m_StatBmp, m_rect.x, m_rect.y,
true);
156 dc.DrawBitmap(m_StatBmp, m_rect.x, m_rect.y,
true);
161 dc.DrawBitmap(m_StatBmp, m_rect.x, m_rect.y,
true);
166bool ocpnCompass::MouseEvent(wxMouseEvent& event) {
171 if (!logicalRect.Contains(event.GetPosition())) {
176 if (event.LeftDown()) {
177 if (m_parent->GetUpMode() == NORTH_UP_MODE)
178 m_parent->SetUpMode(COURSE_UP_MODE);
179 else if (m_parent->GetUpMode() == COURSE_UP_MODE)
180 m_parent->SetUpMode(HEAD_UP_MODE);
182 m_parent->SetUpMode(NORTH_UP_MODE);
188void ocpnCompass::SetColorScheme(ColorScheme cs) {
194#ifdef wxHAS_DPI_INDEPENDENT_PIXELS
195#if wxCHECK_VERSION(3, 1, 6)
196 wxRect logicalRect = wxRect(m_parent->FromPhys(m_rect.GetPosition()),
197 m_parent->FromPhys(m_rect.GetSize()));
199 double scaleFactor = m_parent->GetContentScaleFactor();
201 wxPoint(m_rect.GetX() / scaleFactor, m_rect.GetY() / scaleFactor),
202 wxSize(m_rect.GetWidth() / scaleFactor,
203 m_rect.GetHeight() / scaleFactor));
207 wxRect logicalRect = m_rect;
212void ocpnCompass::UpdateStatus(
bool bnew) {
213 if (bnew) m_lastgpsIconName.Clear();
218 if (g_bopengl && m_texobj) CreateTexture();
222void ocpnCompass::SetScaleFactor(
float factor) {
231 wxBitmap compassBg, gpsBg;
232 int orient = style->GetOrientation();
233 style->SetOrientation(wxTB_HORIZONTAL);
234 if (style->HasBackground()) {
235 compassBg = style->GetNormalBG();
236 style->DrawToolbarLineStart(compassBg);
237 compassBg = style->SetBitmapBrightness(compassBg, m_cs);
238 gpsBg = style->GetNormalBG();
239 style->DrawToolbarLineEnd(gpsBg);
240 gpsBg = style->SetBitmapBrightness(gpsBg, m_cs);
243 if (fabs(m_scale - 1.0) > 0.1) {
244 wxImage bg_img = compassBg.ConvertToImage();
245 bg_img.Rescale(compassBg.GetWidth() * m_scale,
246 compassBg.GetHeight() * m_scale, wxIMAGE_QUALITY_NORMAL);
247 compassBg = wxBitmap(bg_img);
249 bg_img = gpsBg.ConvertToImage();
250 bg_img.Rescale(gpsBg.GetWidth() * m_scale, gpsBg.GetHeight() * m_scale,
251 wxIMAGE_QUALITY_NORMAL);
252 gpsBg = wxBitmap(bg_img);
256 compassBg.GetWidth() + gpsBg.GetWidth() + style->GetCompassLeftMargin();
257 if (!style->marginsInvisible)
258 width += style->GetCompassLeftMargin() + style->GetToolSeparation();
260 m_rect = wxRect(style->GetCompassXOffset(), style->GetCompassYOffset(), width,
261 compassBg.GetHeight() + style->GetCompassTopMargin() +
262 style->GetCompassBottomMargin());
265void ocpnCompass::CreateBmp(
bool newColorScheme) {
268 wxString gpsIconName;
274 static wxBitmap compassBg, gpsBg;
275 static wxSize toolsize;
276 static int topmargin, leftmargin, radius;
278 if (!compassBg.IsOk() || newColorScheme) {
279 int orient = style->GetOrientation();
280 style->SetOrientation(wxTB_HORIZONTAL);
281 if (style->HasBackground()) {
282 compassBg = style->GetNormalBG();
283 style->DrawToolbarLineStart(compassBg);
284 compassBg = style->SetBitmapBrightness(compassBg, m_cs);
285 gpsBg = style->GetNormalBG();
286 style->DrawToolbarLineEnd(gpsBg);
287 gpsBg = style->SetBitmapBrightness(gpsBg, m_cs);
290 if (fabs(m_scale - 1.0) > 0.1) {
291 wxImage bg_img = compassBg.ConvertToImage();
292 bg_img.Rescale(compassBg.GetWidth() * m_scale,
293 compassBg.GetHeight() * m_scale, wxIMAGE_QUALITY_NORMAL);
294 compassBg = wxBitmap(bg_img);
296 bg_img = gpsBg.ConvertToImage();
297 bg_img.Rescale(gpsBg.GetWidth() * m_scale, gpsBg.GetHeight() * m_scale,
298 wxIMAGE_QUALITY_NORMAL);
299 gpsBg = wxBitmap(bg_img);
302 leftmargin = style->GetCompassLeftMargin();
303 topmargin = style->GetCompassTopMargin();
304 radius = style->GetCompassCornerRadius();
306 if (orient == wxTB_VERTICAL) style->SetOrientation(wxTB_VERTICAL);
309 bool b_need_refresh =
false;
313 gpsIconName =
"gps3Bar";
314 if (g_SatsInView <= 8) gpsIconName =
"gps2Bar";
315 if (g_SatsInView <= 4) gpsIconName =
"gps1Bar";
316 if (g_SatsInView < 0) gpsIconName =
"gpsGry";
319 gpsIconName =
"gpsGrn";
321 gpsIconName =
"gpsRed";
323 if (m_lastgpsIconName != gpsIconName) b_need_refresh =
true;
325 double rose_angle = -999.;
327 if ((fabs(m_parent->GetVPRotation()) > .01) ||
328 (fabs(m_parent->GetVPSkew()) > .01)) {
329 rose_angle = -m_parent->GetVPRotation();
333 if (fabs(m_rose_angle - rose_angle) > .1) b_need_refresh =
true;
337 int width = compassBg.GetWidth();
338 if (m_bshowGPS) width += gpsBg.GetWidth() + leftmargin;
340 if (!style->marginsInvisible)
341 width += leftmargin + style->GetToolSeparation();
343 m_StatBmp.Create(width, compassBg.GetHeight() + topmargin +
344 style->GetCompassBottomMargin());
346 m_rect.width = m_StatBmp.GetWidth();
347 m_rect.height = m_StatBmp.GetHeight();
351 m_MaskBmp = wxBitmap(m_StatBmp.GetWidth(), m_StatBmp.GetHeight());
352 if (style->marginsInvisible) {
353 wxMemoryDC sdc(m_MaskBmp);
354 sdc.SetBackground(*wxWHITE_BRUSH);
356 sdc.SetBrush(*wxBLACK_BRUSH);
357 sdc.SetPen(*wxBLACK_PEN);
358 wxSize maskSize = wxSize(m_MaskBmp.GetWidth() - leftmargin,
359 m_MaskBmp.GetHeight() - (2 * topmargin));
360 sdc.DrawRoundedRectangle(wxPoint(leftmargin, topmargin), maskSize, radius);
361 sdc.SelectObject(wxNullBitmap);
363 wxMemoryDC sdc(m_MaskBmp);
364 sdc.SetBackground(*wxWHITE_BRUSH);
366 sdc.SetBrush(*wxBLACK_BRUSH);
367 sdc.SetPen(*wxBLACK_PEN);
368 sdc.DrawRoundedRectangle(0, 0, m_MaskBmp.GetWidth(), m_MaskBmp.GetHeight(),
370 sdc.SelectObject(wxNullBitmap);
372#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
373 m_StatBmp.SetMask(
new wxMask(m_MaskBmp, *wxWHITE));
377 mdc.SelectObject(m_StatBmp);
378 mdc.SetBackground(wxBrush(GetGlobalColor(
"COMP1"), wxBRUSHSTYLE_SOLID));
381 mdc.SetPen(wxPen(GetGlobalColor(
"UITX1"), 1));
382 mdc.SetBrush(wxBrush(GetGlobalColor(
"UITX1"), wxBRUSHSTYLE_TRANSPARENT));
384 if (!style->marginsInvisible)
385 mdc.DrawRoundedRectangle(0, 0, m_StatBmp.GetWidth(), m_StatBmp.GetHeight(),
388 wxPoint offset(leftmargin, topmargin);
392 wxPoint after_rotate;
394 int cwidth = style->GetToolSize().x * m_scale;
395 int cheight = style->GetToolSize().y * m_scale;
396 cheight = wxMin(cheight, compassBg.GetHeight());
397 cwidth = wxMin(cwidth, cheight);
400 if (m_parent->GetUpMode() == COURSE_UP_MODE)
401 BMPRose = style->GetIcon(
"CompassRose", cwidth, cheight);
402 else if (m_parent->GetUpMode() == HEAD_UP_MODE)
403 BMPRose = style->GetIcon(
"CompassRoseMag", cwidth, cheight);
405 BMPRose = style->GetIcon(
"CompassRoseBlue", cwidth, cheight);
406 if ((fabs(m_parent->GetVPRotation()) > .01) ||
407 (fabs(m_parent->GetVPSkew()) > .01)) {
408 wxImage rose_img = BMPRose.ConvertToImage();
409 wxPoint rot_ctr(cwidth / 2, cheight / 2);
411 rose_img.Rotate(rose_angle, rot_ctr,
true, &after_rotate);
412 BMPRose = wxBitmap(rot_image).GetSubBitmap(
413 wxRect(-after_rotate.x, -after_rotate.y, cwidth, cheight));
418 if (style->HasBackground()) {
419 iconBm = MergeBitmaps(compassBg, BMPRose, wxSize(0, 0));
424 iconBm = ConvertTo24Bit(wxColor(0, 0, 0), iconBm);
426 mdc.DrawBitmap(iconBm, offset);
429 mdc.SetPen(wxPen(GetGlobalColor(
"BLUE3"), 1));
430 mdc.SetBrush(wxBrush(GetGlobalColor(
"BLUE3"), wxBRUSHSTYLE_SOLID));
431 int hight = m_StatBmp.GetHeight();
432 int dot_diam = wxMax(2, hight / 12);
433 mdc.DrawCircle(5, hight - 5, dot_diam);
436 offset.x += iconBm.GetWidth();
437 offset.x += style->GetToolSeparation();
439 m_rose_angle = rose_angle;
443 int twidth = style->GetToolSize().x * m_scale;
444 int theight = style->GetToolSize().y * m_scale;
445 theight = wxMin(cheight, compassBg.GetHeight());
446 int swidth = wxMax(twidth, theight);
447 int sheight = wxMin(twidth, theight);
452 wxBitmap gicon = style->GetIcon(gpsIconName, swidth, sheight);
453 if (gicon.GetHeight() != sheight)
454 gicon = style->GetIcon(gpsIconName, swidth - 1, sheight - 1,
true);
456 if (style->HasBackground()) {
457 iconBm = MergeBitmaps(gpsBg, gicon, wxSize(0, 0));
462 iconBm = ConvertTo24Bit(wxColor(0, 0, 0), iconBm);
463 mdc.DrawBitmap(iconBm, offset);
464 mdc.SelectObject(wxNullBitmap);
466 m_lastgpsIconName = gpsIconName;
470void ocpnCompass::CreateTexture() {
471#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
475 wxImage image = m_StatBmp.ConvertToImage();
476 unsigned char* imgdata = image.GetData();
477 unsigned char* imgalpha = image.GetAlpha();
478 m_tex_w = image.GetWidth();
479 m_tex_h = image.GetHeight();
480 m_image_width = m_tex_w;
481 m_image_height = m_tex_h;
484 int width_pot = m_tex_w;
485 int height_pot = m_tex_h;
487 int xp = image.GetWidth();
488 if (((xp != 0) && !(xp & (xp - 1))))
499 xp = image.GetHeight();
500 if (((xp != 0) && !(xp & (xp - 1))))
512 m_tex_h = height_pot;
514 GLuint format = GL_RGBA;
515 GLuint internalformat = GL_RGBA8;
519 unsigned char* teximage =
520 (
unsigned char*)malloc(stride * m_tex_w * m_tex_h);
522 for (
int i = 0; i < m_image_height; i++) {
523 for (
int j = 0; j < m_image_width; j++) {
524 int s = (i * 3 * m_image_width) + (j * 3);
525 int d = (i * stride * m_tex_w) + (j * stride);
527 teximage[d + 0] = imgdata[s + 0];
528 teximage[d + 1] = imgdata[s + 1];
529 teximage[d + 2] = imgdata[s + 2];
530 teximage[d + 3] = 255;
534 glBindTexture(GL_TEXTURE_2D, m_texobj);
536 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
537 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
538 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
540 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
542 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, m_tex_w, m_tex_h, 0,
543 format, GL_UNSIGNED_BYTE, teximage);
546 glBindTexture(GL_TEXTURE_2D, 0);
553void ocpnCompass::UpdateTexture() {
554#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
558 wxImage image = m_StatBmp.ConvertToImage();
559 unsigned char* imgdata = image.GetData();
560 unsigned char* imgalpha = image.GetAlpha();
561 m_tex_w = image.GetWidth();
562 m_tex_h = image.GetHeight();
563 m_image_width = m_tex_w;
564 m_image_height = m_tex_h;
567 int width_pot = m_tex_w;
568 int height_pot = m_tex_h;
570 int xp = image.GetWidth();
571 if (((xp != 0) && !(xp & (xp - 1))))
582 xp = image.GetHeight();
583 if (((xp != 0) && !(xp & (xp - 1))))
595 m_tex_h = height_pot;
597 GLuint format = GL_RGBA;
598 GLuint internalformat = GL_RGBA8;
602 unsigned char* teximage =
603 (
unsigned char*)malloc(stride * m_tex_w * m_tex_h);
605 for (
int i = 0; i < m_image_height; i++) {
606 for (
int j = 0; j < m_image_width; j++) {
607 int s = (i * 3 * m_image_width) + (j * 3);
608 int d = (i * stride * m_tex_w) + (j * stride);
610 teximage[d + 0] = imgdata[s + 0];
611 teximage[d + 1] = imgdata[s + 1];
612 teximage[d + 2] = imgdata[s + 2];
613 teximage[d + 3] = 255;
617 glBindTexture(GL_TEXTURE_2D, m_texobj);
618 glEnable(GL_TEXTURE_2D);
620 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_tex_w, m_tex_h, format,
621 GL_UNSIGNED_BYTE, teximage);
624 glBindTexture(GL_TEXTURE_2D, 0);
Generic Chart canvas base.
ChartCanvas - Main chart display and interaction component.
wxRect GetLogicalRect(void) const
Return the coordinates of the compass widget, in logical pixels.
Device context class that can use either wxDC or OpenGL for drawing.
Global variables stored in configuration file.