void PCB_RENDER_SETTINGS::ImportLegacyColors( const COLORS_DESIGN_SETTINGS* aSettings ) { // Init board layers colors: for( int i = 0; i < PCB_LAYER_ID_COUNT; i++ ) { m_layerColors[i] = aSettings->GetLayerColor( i ); // Guard: if the alpah channel is too small, the layer is not visible. // clamp it to 0.2 if( m_layerColors[i].a < 0.2 ) m_layerColors[i].a = 0.2; } // Init specific graphic layers colors: for( int i = GAL_LAYER_ID_START; i < GAL_LAYER_ID_END; i++ ) m_layerColors[i] = aSettings->GetItemColor( i ); // Default colors for specific layers (not really board layers). m_layerColors[LAYER_VIAS_HOLES] = COLOR4D( 0.5, 0.4, 0.0, 0.8 ); m_layerColors[LAYER_PADS_PLATEDHOLES] = aSettings->GetItemColor( LAYER_PCB_BACKGROUND ); m_layerColors[LAYER_PADS_NETNAMES] = COLOR4D( 1.0, 1.0, 1.0, 0.9 ); m_layerColors[LAYER_PAD_FR_NETNAMES] = COLOR4D( 1.0, 1.0, 1.0, 0.9 ); m_layerColors[LAYER_PAD_BK_NETNAMES] = COLOR4D( 1.0, 1.0, 1.0, 0.9 ); m_layerColors[LAYER_DRC] = COLOR4D( 1.0, 0.0, 0.0, 0.8 ); // LAYER_PADS_TH, LAYER_NON_PLATEDHOLES, LAYER_ANCHOR ,LAYER_RATSNEST, // LAYER_VIA_THROUGH, LAYER_VIA_BBLIND, LAYER_VIA_MICROVIA // are initialized from aSettings // These colors are not actually used. Set just in case... m_layerColors[LAYER_MOD_TEXT_FR] = m_layerColors[F_SilkS]; m_layerColors[LAYER_MOD_TEXT_BK] = m_layerColors[B_SilkS]; // Netnames for copper layers for( LSEQ cu = LSET::AllCuMask().CuStack(); cu; ++cu ) { const COLOR4D lightLabel( 0.8, 0.8, 0.8, 0.7 ); const COLOR4D darkLabel = lightLabel.Inverted(); PCB_LAYER_ID layer = *cu; if( m_layerColors[layer].GetBrightness() > 0.5 ) m_layerColors[GetNetnameLayer( layer )] = darkLabel; else m_layerColors[GetNetnameLayer( layer )] = lightLabel; } SetBackgroundColor ( aSettings->GetItemColor( LAYER_PCB_BACKGROUND ) ); update(); }
void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) { VECTOR2D size; VECTOR2D position( aPad->GetPosition() ); PAD_SHAPE_T shape; double m, n; double orientation = aPad->GetOrientation(); wxString buffer; // Draw description layer if( IsNetnameLayer( aLayer ) ) { // Is anything that we can display enabled? if( m_pcbSettings.m_netNamesOnPads || m_pcbSettings.m_padNumbers ) { // Min char count to calculate string size const int MIN_CHAR_COUNT = 3; bool displayNetname = ( m_pcbSettings.m_netNamesOnPads && !aPad->GetNetname().empty() ); VECTOR2D padsize = VECTOR2D( aPad->GetSize() ); double maxSize = PCB_RENDER_SETTINGS::MAX_FONT_SIZE; double size = padsize.y; // Keep the size ratio for the font, but make it smaller if( padsize.x < padsize.y ) { orientation += 900.0; size = padsize.x; EXCHG( padsize.x, padsize.y ); } else if( padsize.x == padsize.y ) { // If the text is displayed on a symmetrical pad, do not rotate it orientation = 0.0; } // Font size limits if( size > maxSize ) size = maxSize; m_gal->Save(); m_gal->Translate( position ); // do not display descriptions upside down NORMALIZE_ANGLE_90( orientation ); m_gal->Rotate( -orientation * M_PI / 1800.0 ); // Default font settings m_gal->SetHorizontalJustify( GR_TEXT_HJUSTIFY_CENTER ); m_gal->SetVerticalJustify( GR_TEXT_VJUSTIFY_CENTER ); m_gal->SetBold( false ); m_gal->SetItalic( false ); m_gal->SetMirrored( false ); // Set a proper color for the label const COLOR4D& color = m_pcbSettings.GetColor( aPad, aPad->GetLayer() ); COLOR4D labelColor = m_pcbSettings.GetColor( NULL, aLayer ); if( color.GetBrightness() > 0.5 ) m_gal->SetStrokeColor( labelColor.Inverted() ); else m_gal->SetStrokeColor( labelColor ); VECTOR2D textpos( 0.0, 0.0); // Divide the space, to display both pad numbers and netnames // and set the Y text position to display 2 lines if( displayNetname && m_pcbSettings.m_padNumbers ) { size = size / 2.0; textpos.y = size / 2.0; } if( displayNetname ) { // calculate the size of net name text: double tsize = padsize.x / aPad->GetShortNetname().Length(); tsize = std::min( tsize, size ); // Use a smaller text size to handle interline, pen size.. tsize *= 0.7; VECTOR2D namesize( tsize, tsize ); m_gal->SetGlyphSize( namesize ); m_gal->SetLineWidth( namesize.x / 12.0 ); m_gal->StrokeText( aPad->GetShortNetname(), textpos, 0.0 ); } if( m_pcbSettings.m_padNumbers ) { textpos.y = -textpos.y; aPad->StringPadName( buffer ); int len = buffer.Length(); double tsize = padsize.x / std::max( len, MIN_CHAR_COUNT ); tsize = std::min( tsize, size ); // Use a smaller text size to handle interline, pen size.. tsize *= 0.7; tsize = std::min( tsize, size ); VECTOR2D numsize( tsize, tsize ); m_gal->SetGlyphSize( numsize ); m_gal->SetLineWidth( numsize.x / 12.0 ); m_gal->StrokeText( aPad->GetPadName(), textpos, 0.0 ); } m_gal->Restore(); } return; } // Pad drawing const COLOR4D& color = m_pcbSettings.GetColor( aPad, aLayer ); if( m_pcbSettings.m_sketchMode[PADS_VISIBLE] ) { // Outline mode m_gal->SetIsFill( false ); m_gal->SetIsStroke( true ); m_gal->SetLineWidth( m_pcbSettings.m_outlineWidth ); m_gal->SetStrokeColor( color ); } else { // Filled mode m_gal->SetIsFill( true ); m_gal->SetIsStroke( false ); m_gal->SetFillColor( color ); } m_gal->Save(); m_gal->Translate( VECTOR2D( aPad->GetPosition() ) ); m_gal->Rotate( -aPad->GetOrientation() * M_PI / 1800.0 ); // Choose drawing settings depending on if we are drawing a pad itself or a hole if( aLayer == ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ) ) { // Drawing hole: has same shape as PAD_CIRCLE or PAD_OVAL size = VECTOR2D( aPad->GetDrillSize() ) / 2.0; shape = aPad->GetDrillShape() == PAD_DRILL_OBLONG ? PAD_OVAL : PAD_CIRCLE; } else if( aLayer == SOLDERMASK_N_FRONT || aLayer == SOLDERMASK_N_BACK ) { // Drawing soldermask int soldermaskMargin = aPad->GetSolderMaskMargin(); m_gal->Translate( VECTOR2D( aPad->GetOffset() ) ); size = VECTOR2D( aPad->GetSize().x / 2.0 + soldermaskMargin, aPad->GetSize().y / 2.0 + soldermaskMargin ); shape = aPad->GetShape(); } else if( aLayer == SOLDERPASTE_N_FRONT || aLayer == SOLDERPASTE_N_BACK ) { // Drawing solderpaste int solderpasteMargin = aPad->GetLocalSolderPasteMargin(); m_gal->Translate( VECTOR2D( aPad->GetOffset() ) ); size = VECTOR2D( aPad->GetSize().x / 2.0 + solderpasteMargin, aPad->GetSize().y / 2.0 + solderpasteMargin ); shape = aPad->GetShape(); } else { // Drawing every kind of pad m_gal->Translate( VECTOR2D( aPad->GetOffset() ) ); size = VECTOR2D( aPad->GetSize() ) / 2.0; shape = aPad->GetShape(); } switch( shape ) { case PAD_OVAL: if( size.y >= size.x ) { m = ( size.y - size.x ); n = size.x; if( m_pcbSettings.m_sketchMode[PADS_VISIBLE] ) { // Outline mode m_gal->DrawArc( VECTOR2D( 0, -m ), n, -M_PI, 0 ); m_gal->DrawArc( VECTOR2D( 0, m ), n, M_PI, 0 ); m_gal->DrawLine( VECTOR2D( -n, -m ), VECTOR2D( -n, m ) ); m_gal->DrawLine( VECTOR2D( n, -m ), VECTOR2D( n, m ) ); } else { // Filled mode m_gal->DrawCircle( VECTOR2D( 0, -m ), n ); m_gal->DrawCircle( VECTOR2D( 0, m ), n ); m_gal->DrawRectangle( VECTOR2D( -n, -m ), VECTOR2D( n, m ) ); } } else { m = ( size.x - size.y ); n = size.y; if( m_pcbSettings.m_sketchMode[PADS_VISIBLE] ) { // Outline mode m_gal->DrawArc( VECTOR2D( -m, 0 ), n, M_PI / 2, 3 * M_PI / 2 ); m_gal->DrawArc( VECTOR2D( m, 0 ), n, M_PI / 2, -M_PI / 2 ); m_gal->DrawLine( VECTOR2D( -m, -n ), VECTOR2D( m, -n ) ); m_gal->DrawLine( VECTOR2D( -m, n ), VECTOR2D( m, n ) ); } else { // Filled mode m_gal->DrawCircle( VECTOR2D( -m, 0 ), n ); m_gal->DrawCircle( VECTOR2D( m, 0 ), n ); m_gal->DrawRectangle( VECTOR2D( -m, -n ), VECTOR2D( m, n ) ); } } break; case PAD_RECT: m_gal->DrawRectangle( VECTOR2D( -size.x, -size.y ), VECTOR2D( size.x, size.y ) ); break; case PAD_TRAPEZOID: { std::deque<VECTOR2D> pointList; wxPoint corners[4]; VECTOR2D padSize = VECTOR2D( aPad->GetSize().x, aPad->GetSize().y ) / 2; VECTOR2D deltaPadSize = size - padSize; // = solder[Paste/Mask]Margin or 0 aPad->BuildPadPolygon( corners, wxSize( deltaPadSize.x, deltaPadSize.y ), 0.0 ); pointList.push_back( VECTOR2D( corners[0] ) ); pointList.push_back( VECTOR2D( corners[1] ) ); pointList.push_back( VECTOR2D( corners[2] ) ); pointList.push_back( VECTOR2D( corners[3] ) ); if( m_pcbSettings.m_sketchMode[PADS_VISIBLE] ) { // Add the beginning point to close the outline pointList.push_back( pointList.front() ); m_gal->DrawPolyline( pointList ); } else { m_gal->DrawPolygon( pointList ); } } break; case PAD_CIRCLE: m_gal->DrawCircle( VECTOR2D( 0.0, 0.0 ), size.x ); break; } m_gal->Restore(); }
void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer ) { VECTOR2D start( aTrack->GetStart() ); VECTOR2D end( aTrack->GetEnd() ); int width = aTrack->GetWidth(); if( m_pcbSettings.m_netNamesOnTracks && IsNetnameLayer( aLayer ) ) { // If there is a net name - display it on the track if( aTrack->GetNetCode() > NETINFO_LIST::UNCONNECTED ) { VECTOR2D line = ( end - start ); double length = line.EuclideanNorm(); // Check if the track is long enough to have a netname displayed if( length < 10 * width ) return; const wxString& netName = aTrack->GetShortNetname(); VECTOR2D textPosition = start + line / 2.0; // center of the track double textOrientation = -atan( line.y / line.x ); double textSize = std::min( static_cast<double>( width ), length / netName.length() ); // Set a proper color for the label const COLOR4D& color = m_pcbSettings.GetColor( aTrack, aTrack->GetLayer() ); COLOR4D labelColor = m_pcbSettings.GetColor( NULL, aLayer ); if( color.GetBrightness() > 0.5 ) m_gal->SetStrokeColor( labelColor.Inverted() ); else m_gal->SetStrokeColor( labelColor ); m_gal->SetLineWidth( width / 10.0 ); m_gal->SetBold( false ); m_gal->SetItalic( false ); m_gal->SetMirrored( false ); m_gal->SetGlyphSize( VECTOR2D( textSize * 0.7, textSize * 0.7 ) ); m_gal->SetHorizontalJustify( GR_TEXT_HJUSTIFY_CENTER ); m_gal->SetVerticalJustify( GR_TEXT_VJUSTIFY_CENTER ); m_gal->StrokeText( netName, textPosition, textOrientation ); } } else if( IsCopperLayer( aLayer ) ) { // Draw a regular track const COLOR4D& color = m_pcbSettings.GetColor( aTrack, aLayer ); m_gal->SetStrokeColor( color ); m_gal->SetIsStroke( true ); if( m_pcbSettings.m_sketchMode[TRACKS_VISIBLE] ) { // Outline mode m_gal->SetLineWidth( m_pcbSettings.m_outlineWidth ); m_gal->SetIsFill( false ); } else { // Filled mode m_gal->SetFillColor( color ); m_gal->SetIsFill( true ); } m_gal->DrawSegment( start, end, width ); } }