void D_PAD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDraw_mode, const wxPoint& aOffset ) { wxSize mask_margin; // margin (clearance) used for some non copper layers #ifdef SHOW_PADMASK_REAL_SIZE_AND_COLOR int showActualMaskSize = 0; /* Layer number if the actual pad size on mask layer can * be displayed i.e. if only one layer is shown for this pad * and this layer is a mask (solder mask or solder paste */ #endif if( m_Flags & DO_NOT_DRAW ) return; PAD_DRAWINFO drawInfo; drawInfo.m_Offset = aOffset; /* We can show/hide pads from the layer manager. * options are show/hide pads on front and/or back side of the board * For through pads, we hide them only if both sides are hidden. * smd pads on back are hidden for all layers (copper and technical layers) * on back side of the board * smd pads on front are hidden for all layers (copper and technical layers) * on front side of the board * ECO, edge and Draw layers and not considered */ BOARD* brd = GetBoard(); bool frontVisible = brd->IsElementVisible( PCB_VISIBLE( PAD_FR_VISIBLE ) ); bool backVisible = brd->IsElementVisible( PCB_VISIBLE( PAD_BK_VISIBLE ) ); if( !frontVisible && !backVisible ) return; // If pad is only on front side (no layer on back side) // and if hide front side pads is enabled, do not draw if( !frontVisible && !( m_layerMask & LSET::BackMask() ).any() ) return; // If pad is only on back side (no layer on front side) // and if hide back side pads is enabled, do not draw if( !backVisible && !( m_layerMask & LSET::FrontMask() ).any() ) return; PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) aPanel->GetParent(); wxCHECK_RET( frame != NULL, wxT( "Panel has no parent frame window." ) ); DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)frame->GetDisplayOptions(); PCB_SCREEN* screen = frame->GetScreen(); if( displ_opts && displ_opts->m_DisplayPadFill == SKETCH ) drawInfo.m_ShowPadFilled = false; else drawInfo.m_ShowPadFilled = true; EDA_COLOR_T color = BLACK; if( m_layerMask[F_Cu] ) { color = brd->GetVisibleElementColor( PAD_FR_VISIBLE ); } if( m_layerMask[B_Cu] ) { color = ColorMix( color, brd->GetVisibleElementColor( PAD_BK_VISIBLE ) ); } if( color == BLACK ) // Not on a visible copper layer (i.e. still nothing to show) { // If the pad is on only one tech layer, use the layer color else use DARKGRAY LSET mask_non_copper_layers = m_layerMask & ~LSET::AllCuMask(); #ifdef SHOW_PADMASK_REAL_SIZE_AND_COLOR mask_non_copper_layers &= brd->GetVisibleLayers(); #endif LAYER_ID pad_layer = mask_non_copper_layers.ExtractLayer(); switch( (int) pad_layer ) { case UNDEFINED_LAYER: // More than one layer color = DARKGRAY; break; case UNSELECTED_LAYER: // Shouldn't really happen... break; default: color = brd->GetLayerColor( pad_layer ); #ifdef SHOW_PADMASK_REAL_SIZE_AND_COLOR showActualMaskSize = pad_layer; #endif } } // if SMD or connector pad and high contrast mode if( ( aDraw_mode & GR_ALLOW_HIGHCONTRAST ) && ( GetAttribute() == PAD_SMD || GetAttribute() == PAD_CONN ) && displ_opts && displ_opts->m_ContrastModeDisplay ) { // when routing tracks if( frame->GetToolId() == ID_TRACK_BUTT ) { LAYER_ID routeTop = screen->m_Route_Layer_TOP; LAYER_ID routeBot = screen->m_Route_Layer_BOTTOM; // if routing between copper and component layers, // or the current layer is one of said 2 external copper layers, // then highlight only the current layer. if( ( screen->m_Active_Layer == F_Cu || screen->m_Active_Layer == B_Cu ) || ( routeTop==F_Cu && routeBot==B_Cu ) || ( routeTop==B_Cu && routeBot==F_Cu ) ) { if( !IsOnLayer( screen->m_Active_Layer ) ) ColorTurnToDarkDarkGray( &color ); } // else routing between an internal signal layer and some other // layer. Grey out all PAD_SMD pads not on current or the single // selected external layer. else if( !IsOnLayer( screen->m_Active_Layer ) && !IsOnLayer( routeTop ) && !IsOnLayer( routeBot ) ) { ColorTurnToDarkDarkGray( &color ); } } // when not edting tracks, show PAD_SMD components not on active layer // as greyed out else { if( !IsOnLayer( screen->m_Active_Layer ) ) ColorTurnToDarkDarkGray( &color ); } } #ifdef SHOW_PADMASK_REAL_SIZE_AND_COLOR if( showActualMaskSize ) { switch( showActualMaskSize ) { case B_Mask: case F_Mask: mask_margin.x = mask_margin.y = GetSolderMaskMargin(); break; case B_Paste: case F_Paste: mask_margin = GetSolderPasteMargin(); break; default: // Another layer which has no margin to handle break; } } #endif // if Contrast mode is ON and a technical layer active, show pads on this // layer so we can see pads on paste or solder layer and the size of the // mask if( ( aDraw_mode & GR_ALLOW_HIGHCONTRAST ) && displ_opts && displ_opts->m_ContrastModeDisplay && !IsCopperLayer( screen->m_Active_Layer ) ) { if( IsOnLayer( screen->m_Active_Layer ) ) { color = brd->GetLayerColor( screen->m_Active_Layer ); // In high contrast mode, and if the active layer is the mask // layer shows the pad size with the mask clearance switch( screen->m_Active_Layer ) { case B_Mask: case F_Mask: mask_margin.x = mask_margin.y = GetSolderMaskMargin(); break; case B_Paste: case F_Paste: mask_margin = GetSolderPasteMargin(); break; default: break; } } else color = DARKDARKGRAY; } if( aDraw_mode & GR_HIGHLIGHT ) ColorChangeHighlightFlag( &color, !(aDraw_mode & GR_AND) ); ColorApplyHighlightFlag( &color ); bool DisplayIsol = displ_opts && displ_opts->m_DisplayPadIsol; if( !( m_layerMask & LSET::AllCuMask() ).any() ) DisplayIsol = false; if( ( GetAttribute() == PAD_HOLE_NOT_PLATED ) && brd->IsElementVisible( NON_PLATED_VISIBLE ) ) { drawInfo.m_ShowNotPlatedHole = true; drawInfo.m_NPHoleColor = brd->GetVisibleElementColor( NON_PLATED_VISIBLE ); } drawInfo.m_DrawMode = aDraw_mode; drawInfo.m_Color = color; drawInfo.m_DrawPanel = aPanel; drawInfo.m_Mask_margin = mask_margin; drawInfo.m_ShowNCMark = brd->IsElementVisible( PCB_VISIBLE( NO_CONNECTS_VISIBLE ) ); drawInfo.m_IsPrinting = screen->m_IsPrinting; SetAlpha( &color, 170 ); /* Get the pad clearance. This has a meaning only for Pcbnew. * for CvPcb GetClearance() creates debug errors because * there is no net classes so a call to GetClearance() is made only when * needed (never needed in CvPcb) */ drawInfo.m_PadClearance = DisplayIsol ? GetClearance() : 0; // Draw the pad number if( displ_opts && !displ_opts->m_DisplayPadNum ) drawInfo.m_Display_padnum = false; if( displ_opts && (( displ_opts ->m_DisplayNetNamesMode == 0 ) || ( displ_opts->m_DisplayNetNamesMode == 2 )) ) drawInfo.m_Display_netname = false; // Display net names is restricted to pads that are on the active layer // in high contrast mode display if( ( aDraw_mode & GR_ALLOW_HIGHCONTRAST ) && !IsOnLayer( screen->m_Active_Layer ) && displ_opts && displ_opts->m_ContrastModeDisplay ) drawInfo.m_Display_netname = false; DrawShape( aPanel->GetClipBox(), aDC, drawInfo ); }
void D_PAD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDraw_mode, const wxPoint& aOffset ) { int color = 0; wxSize mask_margin; // margin (clearance) used for some non copper layers #ifdef SHOW_PADMASK_REAL_SIZE_AND_COLOR int showActualMaskSize = 0; /* Layer number if the actual pad size on mask layer can * be displayed i.e. if only one layer is shown for this pad * and this layer is a mask (solder mask or sloder paste */ #endif if( m_Flags & DO_NOT_DRAW ) return; PAD_DRAWINFO drawInfo; drawInfo.m_Offset = aOffset; /* We can show/hide pads from the layer manager. * options are show/hide pads on front and/or back side of the board * For through pads, we hide them only if both sides are hidden. * smd pads on back are hidden for all layers (copper and technical layers) * on back side of the board * smd pads on front are hidden for all layers (copper and technical layers) * on front side of the board * ECO, edge and Draw layers and not considered */ // Mask layers for Back side of board #define BACK_SIDE_LAYERS \ (LAYER_BACK | ADHESIVE_LAYER_BACK | SOLDERPASTE_LAYER_BACK \ | SILKSCREEN_LAYER_BACK | SOLDERMASK_LAYER_BACK) // Mask layers for Front side of board #define FRONT_SIDE_LAYERS \ (LAYER_FRONT | ADHESIVE_LAYER_FRONT | SOLDERPASTE_LAYER_FRONT \ | SILKSCREEN_LAYER_FRONT | SOLDERMASK_LAYER_FRONT) BOARD* brd = GetBoard(); bool frontVisible = brd->IsElementVisible( PCB_VISIBLE( PAD_FR_VISIBLE ) ); bool backVisible = brd->IsElementVisible( PCB_VISIBLE( PAD_BK_VISIBLE ) ); if( !frontVisible && !backVisible ) return; /* If pad are only on front side (no layer on back side) * and if hide front side pads is enabled, do not draw */ if( !frontVisible && ( (m_layerMask & BACK_SIDE_LAYERS) == 0 ) ) return; /* If pad are only on back side (no layer on front side) * and if hide back side pads is enabled, do not draw */ if( !backVisible && ( (m_layerMask & FRONT_SIDE_LAYERS) == 0 ) ) return; PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) aPanel->GetParent(); PCB_SCREEN* screen = frame->GetScreen(); if( frame->m_DisplayPadFill == FILLED ) drawInfo.m_ShowPadFilled = true; else drawInfo.m_ShowPadFilled = false; if( m_layerMask & LAYER_FRONT ) { color = brd->GetVisibleElementColor( PAD_FR_VISIBLE ); } if( m_layerMask & LAYER_BACK ) { color |= brd->GetVisibleElementColor( PAD_BK_VISIBLE ); } if( color == 0 ) /* Not on copper layer */ { // If the pad in on only one tech layer, use the layer color else use DARKGRAY int mask_non_copper_layers = m_layerMask & ~ALL_CU_LAYERS; #ifdef SHOW_PADMASK_REAL_SIZE_AND_COLOR mask_non_copper_layers &= brd->GetVisibleLayers(); #endif switch( mask_non_copper_layers ) { case 0: break; case ADHESIVE_LAYER_BACK: color = brd->GetLayerColor( ADHESIVE_N_BACK ); break; case ADHESIVE_LAYER_FRONT: color = brd->GetLayerColor( ADHESIVE_N_FRONT ); break; case SOLDERPASTE_LAYER_BACK: color = brd->GetLayerColor( SOLDERPASTE_N_BACK ); #ifdef SHOW_PADMASK_REAL_SIZE_AND_COLOR showActualMaskSize = SOLDERPASTE_N_BACK; #endif break; case SOLDERPASTE_LAYER_FRONT: color = brd->GetLayerColor( SOLDERPASTE_N_FRONT ); #ifdef SHOW_PADMASK_REAL_SIZE_AND_COLOR showActualMaskSize = SOLDERPASTE_N_FRONT; #endif break; case SILKSCREEN_LAYER_BACK: color = brd->GetLayerColor( SILKSCREEN_N_BACK ); break; case SILKSCREEN_LAYER_FRONT: color = brd->GetLayerColor( SILKSCREEN_N_FRONT ); break; case SOLDERMASK_LAYER_BACK: color = brd->GetLayerColor( SOLDERMASK_N_BACK ); #ifdef SHOW_PADMASK_REAL_SIZE_AND_COLOR showActualMaskSize = SOLDERMASK_N_BACK; #endif break; case SOLDERMASK_LAYER_FRONT: color = brd->GetLayerColor( SOLDERMASK_N_FRONT ); #ifdef SHOW_PADMASK_REAL_SIZE_AND_COLOR showActualMaskSize = SOLDERMASK_N_FRONT; #endif break; case DRAW_LAYER: color = brd->GetLayerColor( DRAW_N ); break; case COMMENT_LAYER: color = brd->GetLayerColor( COMMENT_N ); break; case ECO1_LAYER: color = brd->GetLayerColor( ECO1_N ); break; case ECO2_LAYER: color = brd->GetLayerColor( ECO2_N ); break; case EDGE_LAYER: color = brd->GetLayerColor( EDGE_N ); break; default: color = DARKGRAY; break; } } // if PAD_SMD pad and high contrast mode if( ( aDraw_mode & GR_ALLOW_HIGHCONTRAST ) && ( GetAttribute() == PAD_SMD || GetAttribute() == PAD_CONN ) && DisplayOpt.ContrastModeDisplay ) { // when routing tracks if( frame && frame->GetToolId() == ID_TRACK_BUTT ) { int routeTop = screen->m_Route_Layer_TOP; int routeBot = screen->m_Route_Layer_BOTTOM; // if routing between copper and component layers, // or the current layer is one of said 2 external copper layers, // then highlight only the current layer. if( ( ( 1 << routeTop ) | ( 1 << routeBot ) ) == ( LAYER_BACK | LAYER_FRONT ) || ( ( 1 << screen->m_Active_Layer ) & ( LAYER_BACK | LAYER_FRONT ) ) ) { if( !IsOnLayer( screen->m_Active_Layer ) ) { color &= ~MASKCOLOR; color |= DARKDARKGRAY; } } // else routing between an internal signal layer and some other // layer. Grey out all PAD_SMD pads not on current or the single // selected external layer. else if( !IsOnLayer( screen->m_Active_Layer ) && !IsOnLayer( routeTop ) && !IsOnLayer( routeBot ) ) { color &= ~MASKCOLOR; color |= DARKDARKGRAY; } } // when not edting tracks, show PAD_SMD components not on active layer // as greyed out else { if( !IsOnLayer( screen->m_Active_Layer ) ) { color &= ~MASKCOLOR; color |= DARKDARKGRAY; } } } #ifdef SHOW_PADMASK_REAL_SIZE_AND_COLOR if( showActualMaskSize ) { switch( showActualMaskSize ) { case SOLDERMASK_N_BACK: case SOLDERMASK_N_FRONT: mask_margin.x = mask_margin.y = GetSolderMaskMargin(); break; case SOLDERPASTE_N_BACK: case SOLDERPASTE_N_FRONT: mask_margin = GetSolderPasteMargin(); break; default: break; } } #endif // if Contrast mode is ON and a technical layer active, show pads on this // layer so we can see pads on paste or solder layer and the size of the // mask if( ( aDraw_mode & GR_ALLOW_HIGHCONTRAST ) && DisplayOpt.ContrastModeDisplay && screen->m_Active_Layer > LAST_COPPER_LAYER ) { if( IsOnLayer( screen->m_Active_Layer ) ) { color = brd->GetLayerColor( screen->m_Active_Layer ); // In hight contrast mode, and if the active layer is the mask // layer shows the pad size with the mask clearance switch( screen->m_Active_Layer ) { case SOLDERMASK_N_BACK: case SOLDERMASK_N_FRONT: mask_margin.x = mask_margin.y = GetSolderMaskMargin(); break; case SOLDERPASTE_N_BACK: case SOLDERPASTE_N_FRONT: mask_margin = GetSolderPasteMargin(); break; default: break; } } else color = DARKDARKGRAY; } if( aDraw_mode & GR_HIGHLIGHT ) { if( aDraw_mode & GR_AND ) color &= ~HIGHLIGHT_FLAG; else color |= HIGHLIGHT_FLAG; } if( color & HIGHLIGHT_FLAG ) color = ColorRefs[color & MASKCOLOR].m_LightColor; bool DisplayIsol = DisplayOpt.DisplayPadIsol; if( ( m_layerMask & ALL_CU_LAYERS ) == 0 ) DisplayIsol = false; if( GetAttribute() == PAD_HOLE_NOT_PLATED ) drawInfo.m_ShowNotPlatedHole = true; drawInfo.m_DrawMode = aDraw_mode; drawInfo.m_Color = color; drawInfo.m_DrawPanel = aPanel; drawInfo.m_Mask_margin = mask_margin; drawInfo.m_ShowNCMark = brd->IsElementVisible( PCB_VISIBLE( NO_CONNECTS_VISIBLE ) ); drawInfo.m_IsPrinting = screen->m_IsPrinting; SetAlpha( &color, 170 ); /* Get the pad clearance. This has a meaning only for Pcbnew. * for CvPcb (and GerbView) GetClearance() creates debug errors because * there is no net classes so a call to GetClearance() is made only when * needed (never needed in CvPcb nor in GerbView) */ drawInfo.m_PadClearance = DisplayIsol ? GetClearance() : 0; /* Draw the pad number */ if( frame && !frame->m_DisplayPadNum ) drawInfo.m_Display_padnum = false; if( ( DisplayOpt.DisplayNetNamesMode == 0 ) || ( DisplayOpt.DisplayNetNamesMode == 2 ) ) drawInfo.m_Display_netname = false; // Display net names is restricted to pads that are on the active layer // in hight contrast mode display if( ( aDraw_mode & GR_ALLOW_HIGHCONTRAST ) && !IsOnLayer( screen->m_Active_Layer ) && DisplayOpt.ContrastModeDisplay ) drawInfo.m_Display_netname = false; DrawShape( aPanel->GetClipBox(), aDC, drawInfo ); }