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 }
void Piano::Paint( int y, ocpnDC& dc, wxDC *shapeDC ) { if(shapeDC) { shapeDC->SetBackground( *wxBLACK_BRUSH); shapeDC->SetBrush( *wxWHITE_BRUSH); shapeDC->SetPen( *wxWHITE_PEN); shapeDC->Clear(); } ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle(); if(!style->chartStatusWindowTransparent) { dc.SetPen( *wxTRANSPARENT_PEN ); dc.SetBrush( m_backBrush ); dc.DrawRectangle( 0, y, cc1->GetClientSize().x, GetHeight() ); } // Create the Piano Keys int nKeys = m_key_array.GetCount(); wxPen ppPen( GetGlobalColor( _T("CHBLK") ), 1, wxPENSTYLE_SOLID ); dc.SetPen( ppPen ); for( int i = 0; i < nKeys; i++ ) { int key_db_index = m_key_array.Item( i ); if( -1 == key_db_index ) continue; bool selected = InArray(m_active_index_array, key_db_index); if( ChartData->GetDBChartType( key_db_index ) == CHART_TYPE_CM93 || ChartData->GetDBChartType( key_db_index ) == CHART_TYPE_CM93COMP ) { if(selected) dc.SetBrush( m_scBrush ); else dc.SetBrush( m_cBrush ); } else if( ChartData->GetDBChartFamily( key_db_index ) == CHART_FAMILY_VECTOR ) { if(selected) dc.SetBrush( m_svBrush ); else dc.SetBrush( m_vBrush ); } else { // Raster Chart if(selected) dc.SetBrush( m_slBrush ); else dc.SetBrush( m_tBrush ); } #if 0 // Check to see if this box appears in the sub_light array // If so, add a crosshatch pattern to the brush if(InArray(m_eclipsed_index_array, key_db_index)) { wxBrush ebrush( dc.GetBrush().GetColour(), wxCROSSDIAG_HATCH ); dc.SetBrush(ebrush); } #endif if(m_bBusy) dc.SetBrush( m_uvBrush ); wxRect box = KeyRect.Item( i ); box.y += y; if( m_brounded ) { dc.DrawRoundedRectangle( box.x, box.y, box.width, box.height, 4 ); if(shapeDC) shapeDC->DrawRoundedRectangle( box.x, box.y, box.width, box.height, 4 ); } else { dc.DrawRectangle( box.x, box.y, box.width, box.height ); if(shapeDC) shapeDC->DrawRectangle( box ); } if(InArray(m_eclipsed_index_array, key_db_index)) { dc.SetBrush( m_backBrush ); int w = 3; dc.DrawRoundedRectangle( box.x + w, box.y + w, box.width - ( 2 * w ), box.height - ( 2 * w ), 3 ); } // Look in the current noshow array for this index if(InArray(m_noshow_index_array, key_db_index) && m_pInVizIconBmp && m_pInVizIconBmp->IsOk() ) dc.DrawBitmap(ConvertTo24Bit( dc.GetBrush().GetColour(), *m_pInVizIconBmp ), box.x + 4, box.y + 3, false ); // Look in the current skew array for this index if(InArray(m_skew_index_array, key_db_index) && m_pSkewIconBmp && m_pSkewIconBmp->IsOk()) dc.DrawBitmap(ConvertTo24Bit( dc.GetBrush().GetColour(), *m_pSkewIconBmp ), box.x + box.width - m_pSkewIconBmp->GetWidth() - 4, box.y + 2, false ); // Look in the current tmerc array for this index if(InArray(m_tmerc_index_array, key_db_index) && m_pTmercIconBmp && m_pTmercIconBmp->IsOk() ) dc.DrawBitmap(ConvertTo24Bit( dc.GetBrush().GetColour(), *m_pTmercIconBmp ), box.x + box.width - m_pTmercIconBmp->GetWidth() - 4, box.y + 2, false ); // Look in the current poly array for this index if(InArray(m_poly_index_array, key_db_index) && m_pPolyIconBmp && m_pPolyIconBmp->IsOk() ) dc.DrawBitmap(ConvertTo24Bit( dc.GetBrush().GetColour(), *m_pPolyIconBmp ), box.x + box.width - m_pPolyIconBmp->GetWidth() - 4, box.y + 2, false ); } }
void PianoWin::OnPaint( wxPaintEvent& event ) { ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle(); int width, height; GetClientSize( &width, &height ); wxPaintDC dc( this ); wxBitmap shape = wxBitmap( width, height ); wxMemoryDC shapeDc( shape ); shapeDc.SetBackground( *wxBLACK_BRUSH); shapeDc.SetBrush( *wxWHITE_BRUSH); shapeDc.SetPen( *wxWHITE_PEN); shapeDc.Clear(); dc.SetBackground( m_backBrush ); dc.Clear(); // Create the Piano Keys int nKeys = m_key_array.GetCount(); if( nKeys ) { wxPen ppPen( GetGlobalColor( _T("CHBLK") ), 1, wxSOLID ); dc.SetPen( ppPen ); dc.SetBrush( m_tBrush ); for( int i = 0; i < nKeys; i++ ) { int key_db_index = m_key_array.Item( i ); if( -1 == key_db_index ) continue; if( ChartData->GetDBChartType( m_key_array.Item( i ) ) == CHART_TYPE_S57 ) { dc.SetBrush( m_vBrush ); for( unsigned int ino = 0; ino < m_active_index_array.GetCount(); ino++ ) { if( m_active_index_array.Item( ino ) == key_db_index ) // chart is in the active list dc.SetBrush( m_svBrush ); } } else if( ChartData->GetDBChartType( m_key_array.Item( i ) ) == CHART_TYPE_CM93 ) { dc.SetBrush( m_cBrush ); for( unsigned int ino = 0; ino < m_active_index_array.GetCount(); ino++ ) { if( m_active_index_array.Item( ino ) == key_db_index ) // chart is in the active list dc.SetBrush( m_scBrush ); } } else if( ChartData->GetDBChartType( m_key_array.Item( i ) ) == CHART_TYPE_CM93COMP ) { dc.SetBrush( m_cBrush ); for( unsigned int ino = 0; ino < m_active_index_array.GetCount(); ino++ ) { if( m_active_index_array.Item( ino ) == key_db_index ) // chart is in the active list dc.SetBrush( m_scBrush ); } } else { dc.SetBrush( m_tBrush ); for( unsigned int ino = 0; ino < m_active_index_array.GetCount(); ino++ ) { if( m_active_index_array.Item( ino ) == key_db_index ) // chart is in the active list dc.SetBrush( m_slBrush ); } } // Check to see if this box appears in the sub_light array // If so, add a crosshatch pattern to the brush for( unsigned int ino = 0; ino < m_sublite_index_array.GetCount(); ino++ ) { if( m_sublite_index_array.Item( ino ) == key_db_index ) // chart is in the sublite list { wxBrush ebrush( dc.GetBrush().GetColour(), wxCROSSDIAG_HATCH ); // dc.SetBrush(ebrush); } } wxRect box = KeyRegion.Item( i ).GetBox(); if( m_brounded ) { dc.DrawRoundedRectangle( box.x, box.y, box.width, box.height, 4 ); shapeDc.DrawRoundedRectangle( box.x, box.y, box.width, box.height, 4 ); } else { dc.DrawRectangle( box ); shapeDc.DrawRectangle( box ); } for( unsigned int ino = 0; ino < m_sublite_index_array.GetCount(); ino++ ) { if( m_sublite_index_array.Item( ino ) == key_db_index ) { // chart is in the sublite list dc.SetBrush( dc.GetBackground() ); int w = 3; dc.DrawRoundedRectangle( box.x + w, box.y + w, box.width - ( 2 * w ), box.height - ( 2 * w ), 3 ); } } // Look in the current noshow array for this index for( unsigned int ino = 0; ino < m_noshow_index_array.GetCount(); ino++ ) { if( m_noshow_index_array.Item( ino ) == key_db_index ) { // chart is in the noshow list if( m_pInVizIconBmp && m_pInVizIconBmp->IsOk() ) dc.DrawBitmap( ConvertTo24Bit( dc.GetBrush().GetColour(), *m_pInVizIconBmp ), box.x + 4, box.y + 3, false ); break; } } // Look in the current skew array for this index for( unsigned int ino = 0; ino < m_skew_index_array.GetCount(); ino++ ) { if( m_skew_index_array.Item( ino ) == key_db_index ) { // chart is in the list if( m_pSkewIconBmp && m_pSkewIconBmp->IsOk() ) dc.DrawBitmap( ConvertTo24Bit( dc.GetBrush().GetColour(), *m_pSkewIconBmp ), box.x + box.width - m_pSkewIconBmp->GetWidth() - 4, box.y + 2, false ); break; } } // Look in the current tmerc array for this index for( unsigned int ino = 0; ino < m_tmerc_index_array.GetCount(); ino++ ) { if( m_tmerc_index_array.Item( ino ) == key_db_index ) { // chart is in the list if( m_pTmercIconBmp && m_pTmercIconBmp->IsOk() ) dc.DrawBitmap( ConvertTo24Bit( dc.GetBrush().GetColour(), *m_pTmercIconBmp ), box.x + box.width - m_pTmercIconBmp->GetWidth() - 4, box.y + 2, false ); break; } } // Look in the current poly array for this index for( unsigned int ino = 0; ino < m_poly_index_array.GetCount(); ino++ ) { if( m_poly_index_array.Item( ino ) == key_db_index ) { // chart is in the list if( m_pPolyIconBmp && m_pPolyIconBmp->IsOk() ) dc.DrawBitmap( ConvertTo24Bit( dc.GetBrush().GetColour(), *m_pPolyIconBmp ), box.x + box.width - m_pPolyIconBmp->GetWidth() - 4, box.y + 2, false ); break; } } } #ifndef __WXMAC__ if( style->chartStatusWindowTransparent ) ((wxDialog*) GetParent())->SetShape( wxRegion( shape, *wxBLACK, 0 ) ); } else { // SetShape() with a completely empty shape doesn't work, and leaving the shape // but hiding the window causes artifacts when dragging in GL mode on MSW. // The best solution found so far is to show just a single pixel, this is less // disturbing than flashing piano keys when dragging. (wxWidgets 2.8) if( style->chartStatusWindowTransparent ) ((wxDialog*) GetParent())->SetShape( wxRegion( wxRect(0,0,1,1) ) ); } #else }