wxBitmap ocpnFloatingCompassWindow::CreateBmp() { wxString gpsIconName; ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle(); // In order to draw a horizontal compass window when the toolbar is vertical, we // need to save away the sizes and backgrounds for the two icons. static wxBitmap compassBg, gpsBg; static wxSize toolsize; static int topmargin, leftmargin, radius; if( ! compassBg.IsOk() ) { int orient = style->GetOrientation(); style->SetOrientation( wxTB_HORIZONTAL ); if( style->HasBackground() ) { compassBg = style->GetNormalBG(); style->DrawToolbarLineStart( compassBg ); gpsBg = style->GetNormalBG(); style->DrawToolbarLineEnd( gpsBg ); } leftmargin = style->GetLeftMargin(); topmargin = style->GetTopMargin(); toolsize = style->GetToolSize(); toolsize.x *= 2; radius = style->GetToolbarCornerRadius(); if( orient ) style->SetOrientation( wxTB_VERTICAL ); } bool b_need_refresh = false; if( bGPSValid ) { if( g_bSatValid ) { gpsIconName = _T("gps3Bar"); if( g_SatsInView <= 8 ) gpsIconName = _T("gps2Bar"); if( g_SatsInView <= 4 ) gpsIconName = _T("gps1Bar"); if( g_SatsInView < 0 ) gpsIconName = _T("gpsGry"); } else gpsIconName = _T("gpsGrn"); } else gpsIconName = _T("gpsRed"); if( m_lastgpsIconName != gpsIconName ) b_need_refresh = true; double rose_angle = -999.; if( ( fabs( cc1->GetVPRotation() ) > .01 ) || ( fabs( cc1->GetVPSkew() ) > .01 ) ) { rose_angle = -cc1->GetVPRotation(); if( !g_bCourseUp && !g_bskew_comp ) rose_angle = -cc1->GetVPRotation() - cc1->GetVPSkew(); b_need_refresh = true; } else rose_angle = 0.; if( fabs( m_rose_angle - rose_angle ) > .001 ) b_need_refresh = true; if( b_need_refresh ) { wxBitmap StatBmp; StatBmp.Create( ( _img_compass.GetWidth() + _img_gpsRed.GetWidth() ) + style->GetLeftMargin() * 2 + style->GetToolSeparation(), _img_compass.GetHeight() + style->GetTopMargin() + style->GetBottomMargin() ); if( StatBmp.IsOk() ) { wxMemoryDC mdc; mdc.SelectObject( StatBmp ); mdc.SetBackground( wxBrush( GetGlobalColor( _T("GREY2") ), wxSOLID ) ); mdc.Clear(); mdc.SetPen( wxPen( GetGlobalColor( _T("UITX1") ), 1 ) ); mdc.SetBrush( wxBrush( GetGlobalColor( _T("UITX1") ), wxTRANSPARENT ) ); mdc.DrawRoundedRectangle( 0, 0, StatBmp.GetWidth(), StatBmp.GetHeight(), style->GetToolbarCornerRadius() ); wxPoint offset( style->GetLeftMargin(), style->GetTopMargin() ); // Build Compass Rose, rotated... wxBitmap BMPRose; wxPoint after_rotate; if( g_bCourseUp ) BMPRose = style->GetIcon( _T("CompassRose") ); else BMPRose = style->GetIcon( _T("CompassRoseBlue") ); if( ( fabs( cc1->GetVPRotation() ) > .01 ) || ( fabs( cc1->GetVPSkew() ) > .01 ) ) { wxPoint rot_ctr( BMPRose.GetWidth() / 2, BMPRose.GetHeight() / 2 ); wxImage rose_img = BMPRose.ConvertToImage(); wxImage rot_image = rose_img.Rotate( rose_angle, rot_ctr, true, &after_rotate ); BMPRose = wxBitmap( rot_image ).GetSubBitmap( wxRect( -after_rotate.x, -after_rotate.y, BMPRose.GetWidth(), BMPRose.GetHeight()) ); } wxBitmap iconBm; if( style->HasBackground() ) { iconBm = MergeBitmaps( compassBg, BMPRose, wxSize( 0, 0 ) ); } else { iconBm = BMPRose; } mdc.DrawBitmap( iconBm, offset ); offset.x += iconBm.GetWidth(); m_rose_angle = rose_angle; if( style->HasBackground() ) { iconBm = MergeBitmaps( gpsBg, style->GetIcon( gpsIconName ), wxSize( 0, 0 ) ); } else { iconBm = style->GetIcon( gpsIconName ); } mdc.DrawBitmap( iconBm, offset ); mdc.SelectObject( wxNullBitmap ); m_lastgpsIconName = gpsIconName; } if( style->marginsInvisible ) { m_MaskBmp = wxBitmap( StatBmp.GetWidth(), StatBmp.GetHeight() ); wxMemoryDC sdc( m_MaskBmp ); sdc.SetBackground( *wxWHITE_BRUSH ); sdc.Clear(); sdc.SetBrush( *wxBLACK_BRUSH ); sdc.SetPen( *wxBLACK_PEN ); sdc.DrawRoundedRectangle( wxPoint( leftmargin, topmargin ), toolsize, radius ); sdc.SelectObject( wxNullBitmap ); SetShape( wxRegion( m_MaskBmp, *wxWHITE, 0 ) ); } return StatBmp; } else return wxNullBitmap; }
void ocpnCompass::CreateBmp( bool newColorScheme ) { if(!m_shown) return; wxString gpsIconName; ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle(); // In order to draw a horizontal compass window when the toolbar is vertical, we // need to save away the sizes and backgrounds for the two icons. static wxBitmap compassBg, gpsBg; static wxSize toolsize; static int topmargin, leftmargin, radius; if( ! compassBg.IsOk() || newColorScheme ) { int orient = style->GetOrientation(); style->SetOrientation( wxTB_HORIZONTAL ); if( style->HasBackground() ) { compassBg = style->GetNormalBG(); style->DrawToolbarLineStart( compassBg ); compassBg = style->SetBitmapBrightness( compassBg ); gpsBg = style->GetNormalBG(); style->DrawToolbarLineEnd( gpsBg ); gpsBg = style->SetBitmapBrightness( gpsBg ); } if(fabs(m_scale-1.0) > 0.1){ wxImage bg_img = compassBg.ConvertToImage(); bg_img.Rescale(compassBg.GetWidth() * m_scale, compassBg.GetHeight() *m_scale, wxIMAGE_QUALITY_NORMAL); compassBg = wxBitmap( bg_img ); bg_img = gpsBg.ConvertToImage(); bg_img.Rescale(gpsBg.GetWidth() * m_scale, gpsBg.GetHeight() *m_scale, wxIMAGE_QUALITY_NORMAL); gpsBg = wxBitmap( bg_img ); } leftmargin = style->GetCompassLeftMargin(); topmargin = style->GetCompassTopMargin(); radius = style->GetCompassCornerRadius(); if( orient ) style->SetOrientation( wxTB_VERTICAL ); } bool b_need_refresh = false; if( bGPSValid ) { if( g_bSatValid ) { gpsIconName = _T("gps3Bar"); if( g_SatsInView <= 8 ) gpsIconName = _T("gps2Bar"); if( g_SatsInView <= 4 ) gpsIconName = _T("gps1Bar"); if( g_SatsInView < 0 ) gpsIconName = _T("gpsGry"); } else gpsIconName = _T("gpsGrn"); } else gpsIconName = _T("gpsRed"); if( m_lastgpsIconName != gpsIconName ) b_need_refresh = true; double rose_angle = -999.; if( ( fabs( cc1->GetVPRotation() ) > .01 ) || ( fabs( cc1->GetVPSkew() ) > .01 ) ) { rose_angle = -cc1->GetVPRotation(); } else rose_angle = 0.; if( fabs( m_rose_angle - rose_angle ) > .1 ) b_need_refresh = true; if( !b_need_refresh ) return; int width = compassBg.GetWidth() + gpsBg.GetWidth() + leftmargin; if( !style->marginsInvisible ) width += leftmargin + style->GetToolSeparation(); m_StatBmp.Create( width, compassBg.GetHeight() + topmargin + style->GetCompassBottomMargin() ); m_rect.width = m_StatBmp.GetWidth(); m_rect.height = m_StatBmp.GetHeight(); if( !m_StatBmp.IsOk() ) return; m_MaskBmp = wxBitmap( m_StatBmp.GetWidth(), m_StatBmp.GetHeight() ); if( style->marginsInvisible ) { wxMemoryDC sdc( m_MaskBmp ); sdc.SetBackground( *wxWHITE_BRUSH ); sdc.Clear(); sdc.SetBrush( *wxBLACK_BRUSH ); sdc.SetPen( *wxBLACK_PEN ); wxSize maskSize = wxSize(m_MaskBmp.GetWidth() - leftmargin, m_MaskBmp.GetHeight() - (2 * topmargin)); sdc.DrawRoundedRectangle( wxPoint( leftmargin, topmargin ), maskSize, radius ); sdc.SelectObject( wxNullBitmap ); } else if(radius) { wxMemoryDC sdc( m_MaskBmp ); sdc.SetBackground( *wxWHITE_BRUSH ); sdc.Clear(); sdc.SetBrush( *wxBLACK_BRUSH ); sdc.SetPen( *wxBLACK_PEN ); sdc.DrawRoundedRectangle( 0, 0, m_MaskBmp.GetWidth(), m_MaskBmp.GetHeight(), radius ); sdc.SelectObject( wxNullBitmap ); } m_StatBmp.SetMask(new wxMask(m_MaskBmp, *wxWHITE)); wxMemoryDC mdc; mdc.SelectObject( m_StatBmp ); mdc.SetBackground( wxBrush( GetGlobalColor( _T("COMP1") ), wxSOLID ) ); mdc.Clear(); mdc.SetPen( wxPen( GetGlobalColor( _T("UITX1") ), 1 ) ); mdc.SetBrush( wxBrush( GetGlobalColor( _T("UITX1") ), wxTRANSPARENT ) ); if( !style->marginsInvisible ) mdc.DrawRoundedRectangle( 0, 0, m_StatBmp.GetWidth(), m_StatBmp.GetHeight(),radius ); wxPoint offset(leftmargin, topmargin); // Build Compass Rose, rotated... wxBitmap BMPRose; wxPoint after_rotate; int cwidth = style->GetToolSize().x * m_scale; int cheight = style->GetToolSize().y * m_scale; cheight = wxMin(cheight, compassBg.GetHeight()); cwidth = wxMin( cwidth, cheight ); cheight = cwidth; if( g_bCourseUp ) BMPRose = style->GetIcon( _T("CompassRose"), cwidth, cheight ); else BMPRose = style->GetIcon( _T("CompassRoseBlue"), cwidth, cheight ); if( ( fabs( cc1->GetVPRotation() ) > .01 ) || ( fabs( cc1->GetVPSkew() ) > .01 ) ) { wxImage rose_img = BMPRose.ConvertToImage(); wxPoint rot_ctr( cwidth / 2, cheight / 2 ); wxImage rot_image = rose_img.Rotate( rose_angle, rot_ctr, true, &after_rotate ); BMPRose = wxBitmap( rot_image ).GetSubBitmap( wxRect( -after_rotate.x, -after_rotate.y, cwidth, cheight )); } wxBitmap iconBm; if( style->HasBackground() ) { iconBm = MergeBitmaps( compassBg, BMPRose, wxSize( 0, 0 ) ); } else { iconBm = BMPRose; } iconBm = ConvertTo24Bit( wxColor(0,0,0), iconBm); mdc.DrawBitmap( iconBm, offset ); offset.x += iconBm.GetWidth(); offset.x += style->GetToolSeparation(); m_rose_angle = rose_angle; // GPS Icon int twidth = style->GetToolSize().x * m_scale; int theight = style->GetToolSize().y * m_scale; theight = wxMin(cheight, compassBg.GetHeight()); int swidth = wxMax( twidth, theight ); int sheight = wxMin( twidth, theight ); // Sometimes, the SVG renderer gets the size wrong due to some internal rounding error. // If so found, it seems to work OK by just reducing the requested size by one pixel.... wxBitmap gicon = style->GetIcon( gpsIconName, swidth, sheight ); if( gicon.GetHeight() != sheight ) gicon = style->GetIcon( gpsIconName, swidth-1, sheight-1, true ); if( style->HasBackground() ) { iconBm = MergeBitmaps( gpsBg, gicon, wxSize( 0, 0 ) ); } else { iconBm = gicon; } iconBm = ConvertTo24Bit( wxColor(0,0,0), iconBm); mdc.DrawBitmap( iconBm, offset ); mdc.SelectObject( wxNullBitmap ); m_lastgpsIconName = gpsIconName; #if defined(ocpnUSE_GLES) // GLES does not do ocpnDC::DrawBitmap(), so use texture if(g_bopengl){ wxImage image = m_StatBmp.ConvertToImage(); unsigned char *imgdata = image.GetData(); unsigned char *imgalpha = image.GetAlpha(); int tex_w = image.GetWidth(); int tex_h = image.GetHeight(); GLuint format = GL_RGBA; GLuint internalformat = format; int stride = 4; if(imgdata){ unsigned char *teximage = (unsigned char *) malloc( stride * tex_w * tex_h ); for( int j = 0; j < tex_w*tex_h; j++ ){ for( int k = 0; k < 3; k++ ) teximage[j * stride + k] = imgdata[3*j + k]; teximage[j * stride + 3] = imgalpha ? imgalpha[j] : 255; // alpha } if(texobj){ glDeleteTextures(1, &texobj); texobj = 0; } glGenTextures( 1, &texobj ); glBindTexture( GL_TEXTURE_2D, texobj ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST/*GL_LINEAR*/ ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexImage2D( GL_TEXTURE_2D, 0, internalformat, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, teximage ); free(teximage); } } #endif }