27 #include <wx/wxprec.h>
32 #include "model/ocpn_types.h"
33 #include "model/own_ship.h"
38 #include "glChartCanvas.h"
39 #include "ocpn_frame.h"
42 extern bool g_bSatValid;
43 extern int g_SatsInView;
44 extern bool g_bopengl;
47 #define GL_RGBA8 0x8058
50 ocpnCompass::ocpnCompass(
ChartCanvas* parent,
bool bShowGPS) {
52 m_bshowGPS = bShowGPS;
55 _img_compass = style->GetIcon(_T(
"CompassRose"));
56 _img_gpsRed = style->GetIcon(_T(
"gpsRed"));
60 m_pStatBoxToolStaticBmp = NULL;
63 wxRect(style->GetCompassXOffset(), style->GetCompassYOffset(),
64 _img_compass.GetWidth() + _img_gpsRed.GetWidth() +
65 style->GetCompassLeftMargin() * 2 + style->GetToolSeparation(),
66 _img_compass.GetHeight() + style->GetCompassTopMargin() +
67 style->GetCompassBottomMargin());
75 m_cs = GLOBAL_COLOR_SCHEME_RGB;
78 ocpnCompass::~ocpnCompass() {
81 glDeleteTextures(1, &m_texobj);
86 delete m_pStatBoxToolStaticBmp;
89 void ocpnCompass::Paint(
ocpnDC& dc) {
90 if (m_shown && m_StatBmp.IsOk()) {
91 #if defined(ocpnUSE_GLES) || defined(ocpnUSE_GL)
92 if (g_bopengl && !m_texobj){
95 glGenTextures(1, &m_texobj);
99 if (g_bopengl && m_texobj ) {
100 glBindTexture(GL_TEXTURE_2D, m_texobj);
101 glEnable(GL_TEXTURE_2D);
103 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
110 uv[2] = (float)m_image_width / m_tex_w;
112 uv[4] = (float)m_image_width / m_tex_w;
113 uv[5] = (float)m_image_height / m_tex_h;
115 uv[7] = (float)m_image_height / m_tex_h;
118 coords[0] = m_rect.x;
119 coords[1] = m_rect.y;
120 coords[2] = m_rect.x + m_rect.width;
121 coords[3] = m_rect.y;
122 coords[4] = m_rect.x + m_rect.width;
123 coords[5] = m_rect.y + m_rect.height;
124 coords[6] = m_rect.x;
125 coords[7] = m_rect.y + m_rect.height;
127 m_parent->GetglCanvas()->RenderTextures(dc, coords, uv, 4,
134 glVertex2i(m_rect.x, m_rect.y);
135 glTexCoord2f((
float)m_image_width / m_tex_w, 0);
136 glVertex2i(m_rect.x + m_rect.width, m_rect.y);
137 glTexCoord2f((
float)m_image_width / m_tex_w,
138 (
float)m_image_height / m_tex_h);
139 glVertex2i(m_rect.x + m_rect.width, m_rect.y + m_rect.height);
140 glTexCoord2f(0, (
float)m_image_height / m_tex_h);
141 glVertex2i(m_rect.x, m_rect.y + m_rect.height);
146 glDisable(GL_TEXTURE_2D);
152 double scale = m_parent->GetContentScaleFactor();
154 wxImage image = m_StatBmp.ConvertToImage();
155 image.Rescale( image.GetWidth() *
scale, image.GetHeight() *
scale);
156 wxBitmap bmp( image );
157 dc.DrawBitmap(bmp, m_rect.x, m_rect.y,
true);
160 dc.DrawBitmap(m_StatBmp, m_rect.x, m_rect.y,
true);
163 dc.DrawBitmap(m_StatBmp, m_rect.x, m_rect.y,
true);
165 dc.DrawBitmap(m_StatBmp, m_rect.x, m_rect.y,
true);
170 dc.DrawBitmap(m_StatBmp, m_rect.x, m_rect.y,
true);
175 bool ocpnCompass::MouseEvent(wxMouseEvent& event) {
176 if (!m_shown || !m_rect.Contains(event.GetPosition()))
return false;
178 if (event.LeftDown()) {
179 if (m_parent->GetUpMode() == NORTH_UP_MODE)
180 m_parent->SetUpMode(COURSE_UP_MODE);
181 else if (m_parent->GetUpMode() == COURSE_UP_MODE)
182 m_parent->SetUpMode(HEAD_UP_MODE);
184 m_parent->SetUpMode(NORTH_UP_MODE);
190 void ocpnCompass::SetColorScheme(ColorScheme cs) {
195 void ocpnCompass::UpdateStatus(
bool bnew) {
197 m_lastgpsIconName.Clear();
202 if (g_bopengl && m_texobj)
208 void ocpnCompass::SetScaleFactor(
float factor) {
217 wxBitmap compassBg, gpsBg;
218 int orient = style->GetOrientation();
219 style->SetOrientation(wxTB_HORIZONTAL);
220 if (style->HasBackground()) {
221 compassBg = style->GetNormalBG();
222 style->DrawToolbarLineStart(compassBg);
223 compassBg = style->SetBitmapBrightness(compassBg, m_cs);
224 gpsBg = style->GetNormalBG();
225 style->DrawToolbarLineEnd(gpsBg);
226 gpsBg = style->SetBitmapBrightness(gpsBg, m_cs);
229 if (fabs(m_scale - 1.0) > 0.1) {
230 wxImage bg_img = compassBg.ConvertToImage();
231 bg_img.Rescale(compassBg.GetWidth() * m_scale,
232 compassBg.GetHeight() * m_scale, wxIMAGE_QUALITY_NORMAL);
233 compassBg = wxBitmap(bg_img);
235 bg_img = gpsBg.ConvertToImage();
236 bg_img.Rescale(gpsBg.GetWidth() * m_scale, gpsBg.GetHeight() * m_scale,
237 wxIMAGE_QUALITY_NORMAL);
238 gpsBg = wxBitmap(bg_img);
242 compassBg.GetWidth() + gpsBg.GetWidth() + style->GetCompassLeftMargin();
243 if (!style->marginsInvisible)
244 width += style->GetCompassLeftMargin() + style->GetToolSeparation();
246 m_rect = wxRect(style->GetCompassXOffset(), style->GetCompassYOffset(), width,
247 compassBg.GetHeight() + style->GetCompassTopMargin() +
248 style->GetCompassBottomMargin());
251 void ocpnCompass::CreateBmp(
bool newColorScheme) {
254 wxString gpsIconName;
260 static wxBitmap compassBg, gpsBg;
261 static wxSize toolsize;
262 static int topmargin, leftmargin, radius;
264 if (!compassBg.IsOk() || newColorScheme) {
265 int orient = style->GetOrientation();
266 style->SetOrientation(wxTB_HORIZONTAL);
267 if (style->HasBackground()) {
268 compassBg = style->GetNormalBG();
269 style->DrawToolbarLineStart(compassBg);
270 compassBg = style->SetBitmapBrightness(compassBg, m_cs);
271 gpsBg = style->GetNormalBG();
272 style->DrawToolbarLineEnd(gpsBg);
273 gpsBg = style->SetBitmapBrightness(gpsBg, m_cs);
276 if (fabs(m_scale - 1.0) > 0.1) {
277 wxImage bg_img = compassBg.ConvertToImage();
278 bg_img.Rescale(compassBg.GetWidth() * m_scale,
279 compassBg.GetHeight() * m_scale, wxIMAGE_QUALITY_NORMAL);
280 compassBg = wxBitmap(bg_img);
282 bg_img = gpsBg.ConvertToImage();
283 bg_img.Rescale(gpsBg.GetWidth() * m_scale, gpsBg.GetHeight() * m_scale,
284 wxIMAGE_QUALITY_NORMAL);
285 gpsBg = wxBitmap(bg_img);
288 leftmargin = style->GetCompassLeftMargin();
289 topmargin = style->GetCompassTopMargin();
290 radius = style->GetCompassCornerRadius();
292 if (orient == wxTB_VERTICAL) style->SetOrientation(wxTB_VERTICAL);
295 bool b_need_refresh =
false;
299 gpsIconName = _T(
"gps3Bar");
300 if (g_SatsInView <= 8) gpsIconName = _T(
"gps2Bar");
301 if (g_SatsInView <= 4) gpsIconName = _T(
"gps1Bar");
302 if (g_SatsInView < 0) gpsIconName = _T(
"gpsGry");
305 gpsIconName = _T(
"gpsGrn");
307 gpsIconName = _T(
"gpsRed");
309 if (m_lastgpsIconName != gpsIconName) b_need_refresh =
true;
311 double rose_angle = -999.;
313 if ((fabs(m_parent->GetVPRotation()) > .01) ||
314 (fabs(m_parent->GetVPSkew()) > .01)) {
315 rose_angle = -m_parent->GetVPRotation();
319 if (fabs(m_rose_angle - rose_angle) > .1) b_need_refresh =
true;
323 int width = compassBg.GetWidth();
324 if (m_bshowGPS) width += gpsBg.GetWidth() + leftmargin;
326 if (!style->marginsInvisible)
327 width += leftmargin + style->GetToolSeparation();
329 m_StatBmp.Create(width, compassBg.GetHeight() + topmargin +
330 style->GetCompassBottomMargin());
332 m_rect.width = m_StatBmp.GetWidth();
333 m_rect.height = m_StatBmp.GetHeight();
337 m_MaskBmp = wxBitmap(m_StatBmp.GetWidth(), m_StatBmp.GetHeight());
338 if (style->marginsInvisible) {
339 wxMemoryDC sdc(m_MaskBmp);
340 sdc.SetBackground(*wxWHITE_BRUSH);
342 sdc.SetBrush(*wxBLACK_BRUSH);
343 sdc.SetPen(*wxBLACK_PEN);
344 wxSize maskSize = wxSize(m_MaskBmp.GetWidth() - leftmargin,
345 m_MaskBmp.GetHeight() - (2 * topmargin));
346 sdc.DrawRoundedRectangle(wxPoint(leftmargin, topmargin), maskSize, radius);
347 sdc.SelectObject(wxNullBitmap);
349 wxMemoryDC sdc(m_MaskBmp);
350 sdc.SetBackground(*wxWHITE_BRUSH);
352 sdc.SetBrush(*wxBLACK_BRUSH);
353 sdc.SetPen(*wxBLACK_PEN);
354 sdc.DrawRoundedRectangle(0, 0, m_MaskBmp.GetWidth(), m_MaskBmp.GetHeight(),
356 sdc.SelectObject(wxNullBitmap);
358 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
359 m_StatBmp.SetMask(
new wxMask(m_MaskBmp, *wxWHITE));
363 mdc.SelectObject(m_StatBmp);
364 mdc.SetBackground(wxBrush(GetGlobalColor(_T(
"COMP1")), wxBRUSHSTYLE_SOLID));
367 mdc.SetPen(wxPen(GetGlobalColor(_T(
"UITX1")), 1));
368 mdc.SetBrush(wxBrush(GetGlobalColor(_T(
"UITX1")), wxBRUSHSTYLE_TRANSPARENT));
370 if (!style->marginsInvisible)
371 mdc.DrawRoundedRectangle(0, 0, m_StatBmp.GetWidth(), m_StatBmp.GetHeight(),
374 wxPoint offset(leftmargin, topmargin);
378 wxPoint after_rotate;
380 int cwidth = style->GetToolSize().x * m_scale;
381 int cheight = style->GetToolSize().y * m_scale;
382 cheight = wxMin(cheight, compassBg.GetHeight());
383 cwidth = wxMin(cwidth, cheight);
386 if (m_parent->GetUpMode() == COURSE_UP_MODE)
387 BMPRose = style->GetIcon(_T(
"CompassRose"), cwidth, cheight);
388 else if (m_parent->GetUpMode() == HEAD_UP_MODE)
389 BMPRose = style->GetIcon(_T(
"CompassRoseMag"), cwidth, cheight);
391 BMPRose = style->GetIcon(_T(
"CompassRoseBlue"), cwidth, cheight);
392 if ((fabs(m_parent->GetVPRotation()) > .01) ||
393 (fabs(m_parent->GetVPSkew()) > .01)) {
394 wxImage rose_img = BMPRose.ConvertToImage();
395 wxPoint rot_ctr(cwidth / 2, cheight / 2);
397 rose_img.Rotate(rose_angle, rot_ctr,
true, &after_rotate);
398 BMPRose = wxBitmap(rot_image).GetSubBitmap(
399 wxRect(-after_rotate.x, -after_rotate.y, cwidth, cheight));
404 if (style->HasBackground()) {
405 iconBm = MergeBitmaps(compassBg, BMPRose, wxSize(0, 0));
410 iconBm = ConvertTo24Bit(wxColor(0, 0, 0), iconBm);
412 mdc.DrawBitmap(iconBm, offset);
413 offset.x += iconBm.GetWidth();
414 offset.x += style->GetToolSeparation();
416 m_rose_angle = rose_angle;
420 int twidth = style->GetToolSize().x * m_scale;
421 int theight = style->GetToolSize().y * m_scale;
422 theight = wxMin(cheight, compassBg.GetHeight());
423 int swidth = wxMax(twidth, theight);
424 int sheight = wxMin(twidth, theight);
429 wxBitmap gicon = style->GetIcon(gpsIconName, swidth, sheight);
430 if (gicon.GetHeight() != sheight)
431 gicon = style->GetIcon(gpsIconName, swidth - 1, sheight - 1,
true);
433 if (style->HasBackground()) {
434 iconBm = MergeBitmaps(gpsBg, gicon, wxSize(0, 0));
439 iconBm = ConvertTo24Bit(wxColor(0, 0, 0), iconBm);
440 mdc.DrawBitmap(iconBm, offset);
441 mdc.SelectObject(wxNullBitmap);
443 m_lastgpsIconName = gpsIconName;
447 void ocpnCompass::CreateTexture() {
448 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
452 wxImage image = m_StatBmp.ConvertToImage();
453 unsigned char* imgdata = image.GetData();
454 unsigned char* imgalpha = image.GetAlpha();
455 m_tex_w = image.GetWidth();
456 m_tex_h = image.GetHeight();
457 m_image_width = m_tex_w;
458 m_image_height = m_tex_h;
461 int width_pot = m_tex_w;
462 int height_pot = m_tex_h;
464 int xp = image.GetWidth();
465 if (((xp != 0) && !(xp & (xp - 1))))
476 xp = image.GetHeight();
477 if (((xp != 0) && !(xp & (xp - 1))))
489 m_tex_h = height_pot;
491 GLuint format = GL_RGBA;
492 GLuint internalformat = GL_RGBA8;
496 unsigned char* teximage =
497 (
unsigned char*)malloc(stride * m_tex_w * m_tex_h);
499 for (
int i = 0; i < m_image_height; i++) {
500 for (
int j = 0; j < m_image_width; j++) {
501 int s = (i * 3 * m_image_width) + (j * 3);
502 int d = (i * stride * m_tex_w) + (j * stride);
504 teximage[d + 0] = imgdata[s + 0];
505 teximage[d + 1] = imgdata[s + 1];
506 teximage[d + 2] = imgdata[s + 2];
507 teximage[d + 3] = 255;
511 glBindTexture(GL_TEXTURE_2D, m_texobj);
513 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
514 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
515 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
517 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
519 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, m_tex_w, m_tex_h, 0,
520 format, GL_UNSIGNED_BYTE, teximage);
523 glBindTexture(GL_TEXTURE_2D, 0);
530 void ocpnCompass::UpdateTexture() {
531 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
535 wxImage image = m_StatBmp.ConvertToImage();
536 unsigned char* imgdata = image.GetData();
537 unsigned char* imgalpha = image.GetAlpha();
538 m_tex_w = image.GetWidth();
539 m_tex_h = image.GetHeight();
540 m_image_width = m_tex_w;
541 m_image_height = m_tex_h;
544 int width_pot = m_tex_w;
545 int height_pot = m_tex_h;
547 int xp = image.GetWidth();
548 if (((xp != 0) && !(xp & (xp - 1))))
559 xp = image.GetHeight();
560 if (((xp != 0) && !(xp & (xp - 1))))
572 m_tex_h = height_pot;
574 GLuint format = GL_RGBA;
575 GLuint internalformat = GL_RGBA8;
579 unsigned char* teximage =
580 (
unsigned char*)malloc(stride * m_tex_w * m_tex_h);
582 for (
int i = 0; i < m_image_height; i++) {
583 for (
int j = 0; j < m_image_width; j++) {
584 int s = (i * 3 * m_image_width) + (j * 3);
585 int d = (i * stride * m_tex_w) + (j * stride);
587 teximage[d + 0] = imgdata[s + 0];
588 teximage[d + 1] = imgdata[s + 1];
589 teximage[d + 2] = imgdata[s + 2];
590 teximage[d + 3] = 255;
594 glBindTexture(GL_TEXTURE_2D, m_texobj);
595 glEnable(GL_TEXTURE_2D);
597 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_tex_w, m_tex_h, format, GL_UNSIGNED_BYTE, teximage);
600 glBindTexture(GL_TEXTURE_2D, 0);