void LIB_CIRCLE::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, void* aData, const TRANSFORM& aTransform ) { wxPoint pos1 = aTransform.TransformCoordinate( m_Pos ) + aOffset; COLOR4D color = GetLayerColor( LAYER_DEVICE ); COLOR4D bgColor = GetLayerColor( LAYER_DEVICE_BACKGROUND ); FILL_T fill = aData ? NO_FILL : m_Fill; EDA_RECT* const clipbox = aPanel? aPanel->GetClipBox() : NULL; if( fill == FILLED_WITH_BG_BODYCOLOR ) GRFilledCircle( clipbox, aDC, pos1.x, pos1.y, m_Radius, GetPenSize(), bgColor, bgColor ); else if( fill == FILLED_SHAPE ) GRFilledCircle( clipbox, aDC, pos1.x, pos1.y, m_Radius, 0, color, color ); else GRCircle( clipbox, aDC, pos1.x, pos1.y, m_Radius, GetPenSize(), color ); }
void LIB_CIRCLE::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, COLOR4D aColor, GR_DRAWMODE aDrawMode, void* aData, const TRANSFORM& aTransform ) { wxPoint pos1; COLOR4D color = GetLayerColor( LAYER_DEVICE ); if( aColor == COLOR4D::UNSPECIFIED ) // Used normal color or selected color { if( IsSelected() ) color = GetItemSelectedColor(); } else { color = aColor; } pos1 = aTransform.TransformCoordinate( m_Pos ) + aOffset; GRSetDrawMode( aDC, aDrawMode ); FILL_T fill = aData ? NO_FILL : m_Fill; if( aColor != COLOR4D::UNSPECIFIED ) fill = NO_FILL; EDA_RECT* const clipbox = aPanel? aPanel->GetClipBox() : NULL; if( fill == FILLED_WITH_BG_BODYCOLOR ) GRFilledCircle( clipbox, aDC, pos1.x, pos1.y, m_Radius, GetPenSize(), (m_Flags & IS_MOVED) ? color : GetLayerColor( LAYER_DEVICE_BACKGROUND ), GetLayerColor( LAYER_DEVICE_BACKGROUND ) ); else if( fill == FILLED_SHAPE ) GRFilledCircle( clipbox, aDC, pos1.x, pos1.y, m_Radius, 0, color, color ); else GRCircle( clipbox, aDC, pos1.x, pos1.y, m_Radius, GetPenSize(), color ); /* Set to one (1) to draw bounding box around circle to validate bounding * box calculation. */ #if 0 EDA_RECT bBox = GetBoundingBox(); bBox.RevertYAxis(); bBox = aTransform.TransformCoordinate( bBox ); bBox.Move( aOffset ); GRRect( clipbox, aDC, bBox, 0, LIGHTMAGENTA ); #endif }
void LIB_CIRCLE::drawGraphic( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform ) { wxPoint pos1; int color = ReturnLayerColor( LAYER_DEVICE ); if( aColor < 0 ) // Used normal color or selected color { if( IsSelected() ) color = g_ItemSelectetColor; } else { color = aColor; } pos1 = aTransform.TransformCoordinate( m_Pos ) + aOffset; GRSetDrawMode( aDC, aDrawMode ); FILL_T fill = aData ? NO_FILL : m_Fill; if( aColor >= 0 ) fill = NO_FILL; if( fill == FILLED_WITH_BG_BODYCOLOR ) GRFilledCircle( aPanel->GetClipBox(), aDC, pos1.x, pos1.y, m_Radius, GetPenSize(), (m_Flags & IS_MOVED) ? color : ReturnLayerColor( LAYER_DEVICE_BACKGROUND ), ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) ); else if( fill == FILLED_SHAPE ) GRFilledCircle( aPanel->GetClipBox(), aDC, pos1.x, pos1.y, m_Radius, 0, color, color ); else GRCircle( aPanel->GetClipBox(), aDC, pos1.x, pos1.y, m_Radius, GetPenSize(), color ); /* Set to one (1) to draw bounding box around circle to validate bounding * box calculation. */ #if 0 EDA_RECT bBox = GetBoundingBox(); GRRect( aPanel->GetClipBox(), aDC, bBox.GetOrigin().x, bBox.GetOrigin().y, bBox.GetEnd().x, bBox.GetEnd().y, 0, LIGHTMAGENTA ); #endif }
void SCH_JUNCTION::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, int aDrawMode, int aColor ) { int color; if( aColor >= 0 ) color = aColor; else color = ReturnLayerColor( m_Layer ); GRSetDrawMode( aDC, aDrawMode ); GRFilledCircle( aPanel->GetClipBox(), aDC, m_pos.x + aOffset.x, m_pos.y + aOffset.y, ( m_size.x / 2 ), 0, color, color ); }
void SCH_JUNCTION::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, GR_DRAWMODE aDrawMode, COLOR4D aColor ) { COLOR4D color; if( aColor != COLOR4D::UNSPECIFIED ) color = aColor; else color = GetLayerColor( GetState( BRIGHTENED ) ? LAYER_BRIGHTENED : m_Layer ); GRSetDrawMode( aDC, aDrawMode ); GRFilledCircle( aPanel->GetClipBox(), aDC, m_pos.x + aOffset.x, m_pos.y + aOffset.y, ( GetSymbolSize() / 2 ), 0, color, color ); }
void D_CODE::DrawFlashedShape( GERBER_DRAW_ITEM* aParent, EDA_RECT* aClipBox, wxDC* aDC, COLOR4D aColor, wxPoint aShapePos, bool aFilledShape ) { int radius; switch( m_Shape ) { case APT_MACRO: GetMacro()->DrawApertureMacroShape( aParent, aClipBox, aDC, aColor, aShapePos, aFilledShape); break; case APT_CIRCLE: radius = m_Size.x >> 1; if( !aFilledShape ) GRCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos), radius, 0, aColor ); else if( m_DrillShape == APT_DEF_NO_HOLE ) { GRFilledCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos), radius, aColor ); } else if( m_DrillShape == APT_DEF_ROUND_HOLE ) // round hole in shape { int width = (m_Size.x - m_Drill.x ) / 2; GRCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos), radius - (width / 2), width, aColor ); } else // rectangular hole { if( m_Polygon.OutlineCount() == 0 ) ConvertShapeToPolygon(); DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); } break; case APT_RECT: { wxPoint start; start.x = aShapePos.x - m_Size.x / 2; start.y = aShapePos.y - m_Size.y / 2; wxPoint end = start + m_Size; start = aParent->GetABPosition( start ); end = aParent->GetABPosition( end ); if( !aFilledShape ) { GRRect( aClipBox, aDC, start.x, start.y, end.x, end.y, 0, aColor ); } else if( m_DrillShape == APT_DEF_NO_HOLE ) { GRFilledRect( aClipBox, aDC, start.x, start.y, end.x, end.y, 0, aColor, aColor ); } else { if( m_Polygon.OutlineCount() == 0 ) ConvertShapeToPolygon(); DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); } } break; case APT_OVAL: { wxPoint start = aShapePos; wxPoint end = aShapePos; if( m_Size.x > m_Size.y ) // horizontal oval { int delta = (m_Size.x - m_Size.y) / 2; start.x -= delta; end.x += delta; radius = m_Size.y; } else // horizontal oval { int delta = (m_Size.y - m_Size.x) / 2; start.y -= delta; end.y += delta; radius = m_Size.x; } start = aParent->GetABPosition( start ); end = aParent->GetABPosition( end ); if( !aFilledShape ) { GRCSegm( aClipBox, aDC, start.x, start.y, end.x, end.y, radius, aColor ); } else if( m_DrillShape == APT_DEF_NO_HOLE ) { GRFillCSegm( aClipBox, aDC, start.x, start.y, end.x, end.y, radius, aColor ); } else { if( m_Polygon.OutlineCount() == 0 ) ConvertShapeToPolygon(); DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); } } break; case APT_POLYGON: if( m_Polygon.OutlineCount() == 0 ) ConvertShapeToPolygon(); DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); break; } }
void PCB_EDIT_FRAME::PrintPage( wxDC* aDC, LSET aPrintMask, bool aPrintMirrorMode, void* aData) { const GR_DRAWMODE drawmode = (GR_DRAWMODE) 0; DISPLAY_OPTIONS save_opt; BOARD* Pcb = GetBoard(); int defaultPenSize = Millimeter2iu( 0.2 ); bool onePagePerLayer = false; PRINT_PARAMETERS* printParameters = (PRINT_PARAMETERS*) aData; // can be null DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)GetDisplayOptions(); if( printParameters && printParameters->m_OptionPrintPage == 0 ) onePagePerLayer = true; PRINT_PARAMETERS::DrillShapeOptT drillShapeOpt = PRINT_PARAMETERS::FULL_DRILL_SHAPE; if( printParameters ) { drillShapeOpt = printParameters->m_DrillShapeOpt; defaultPenSize = printParameters->m_PenDefaultSize; } save_opt = *displ_opts; LAYER_ID activeLayer = GetScreen()->m_Active_Layer; displ_opts->m_ContrastModeDisplay = false; displ_opts->m_DisplayPadFill = true; displ_opts->m_DisplayViaFill = true; if( !( aPrintMask & LSET::AllCuMask() ).any() ) { if( onePagePerLayer ) { // We can print mask layers (solder mask and solder paste) with the actual // pad sizes. To do that, we must set ContrastModeDisplay to true and set // the GetScreen()->m_Active_Layer to the current printed layer displ_opts->m_ContrastModeDisplay = true; displ_opts->m_DisplayPadFill = true; // Calculate the active layer number to print from its mask layer: GetScreen()->m_Active_Layer = B_Cu; for( LAYER_NUM id = LAYER_ID_COUNT-1; id >= 0; --id ) { if( aPrintMask[id] ) { GetScreen()->m_Active_Layer = LAYER_ID( id ); break; } } // pads on Silkscreen layer are usually plot in sketch mode: if( GetScreen()->m_Active_Layer == B_SilkS || GetScreen()->m_Active_Layer == F_SilkS ) { displ_opts->m_DisplayPadFill = false; } } else { displ_opts->m_DisplayPadFill = false; } } displ_opts->m_DisplayPadNum = false; bool nctmp = GetBoard()->IsElementVisible( NO_CONNECTS_VISIBLE ); GetBoard()->SetElementVisibility( NO_CONNECTS_VISIBLE, false ); bool anchorsTmp = GetBoard()->IsElementVisible( ANCHOR_VISIBLE ); GetBoard()->SetElementVisibility( ANCHOR_VISIBLE, false ); displ_opts->m_DisplayPadIsol = false; displ_opts->m_DisplayModEdgeFill = FILLED; displ_opts->m_DisplayModTextFill = FILLED; displ_opts->m_DisplayPcbTrackFill = true; displ_opts->m_ShowTrackClearanceMode = DO_NOT_SHOW_CLEARANCE; displ_opts->m_DisplayDrawItemsFill = FILLED; displ_opts->m_DisplayZonesMode = 0; displ_opts->m_DisplayNetNamesMode = 0; m_canvas->SetPrintMirrored( aPrintMirrorMode ); for( BOARD_ITEM* item = Pcb->m_Drawings; item; item = item->Next() ) { switch( item->Type() ) { case PCB_LINE_T: case PCB_DIMENSION_T: case PCB_TEXT_T: case PCB_TARGET_T: if( aPrintMask[item->GetLayer()] ) item->Draw( m_canvas, aDC, drawmode ); break; case PCB_MARKER_T: default: break; } } // Print tracks for( TRACK* track = Pcb->m_Track; track; track = track->Next() ) { if( !( aPrintMask & track->GetLayerSet() ).any() ) continue; if( track->Type() == PCB_VIA_T ) // VIA encountered. { int radius = track->GetWidth() / 2; const VIA* via = static_cast<const VIA*>( track ); EDA_COLOR_T color = g_ColorsSettings.GetItemColor( VIAS_VISIBLE + via->GetViaType() ); GRFilledCircle( m_canvas->GetClipBox(), aDC, via->GetStart().x, via->GetStart().y, radius, 0, color, color ); } else { track->Draw( m_canvas, aDC, drawmode ); } } // Outdated: only for compatibility to old boards for( TRACK* track = Pcb->m_Zone; track; track = track->Next() ) { if( !( aPrintMask & track->GetLayerSet() ).any() ) continue; track->Draw( m_canvas, aDC, drawmode ); } // Draw filled areas (i.e. zones) for( int ii = 0; ii < Pcb->GetAreaCount(); ii++ ) { ZONE_CONTAINER* zone = Pcb->GetArea( ii ); if( aPrintMask[zone->GetLayer()] ) zone->DrawFilledArea( m_canvas, aDC, drawmode ); } // Draw footprints, this is done at last in order to print the pad holes in // white after the tracks and zones int tmp = D_PAD::m_PadSketchModePenSize; D_PAD::m_PadSketchModePenSize = defaultPenSize; for( MODULE* module = (MODULE*) Pcb->m_Modules; module; module = module->Next() ) { Print_Module( m_canvas, aDC, module, drawmode, aPrintMask, drillShapeOpt ); } D_PAD::m_PadSketchModePenSize = tmp; /* Print via holes in bg color: Not sure it is good for buried or blind * vias */ if( drillShapeOpt != PRINT_PARAMETERS::NO_DRILL_SHAPE ) { TRACK* track = Pcb->m_Track; EDA_COLOR_T color = WHITE; bool blackpenstate = GetGRForceBlackPenState(); GRForceBlackPen( false ); for( ; track; track = track->Next() ) { if( !( aPrintMask & track->GetLayerSet() ).any() ) continue; if( track->Type() == PCB_VIA_T ) // VIA encountered. { int diameter; const VIA *via = static_cast<const VIA*>( track ); if( drillShapeOpt == PRINT_PARAMETERS::SMALL_DRILL_SHAPE ) diameter = std::min( SMALL_DRILL, via->GetDrillValue() ); else diameter = via->GetDrillValue(); GRFilledCircle( m_canvas->GetClipBox(), aDC, track->GetStart().x, track->GetStart().y, diameter/2, 0, color, color ); } } GRForceBlackPen( blackpenstate ); } m_canvas->SetPrintMirrored( false ); *displ_opts = save_opt; GetScreen()->m_Active_Layer = activeLayer; GetBoard()->SetElementVisibility( NO_CONNECTS_VISIBLE, nctmp ); GetBoard()->SetElementVisibility( ANCHOR_VISIBLE, anchorsTmp ); }
void SCH_SHEET::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, GR_DRAWMODE aDrawMode, COLOR4D aColor ) { COLOR4D txtcolor; wxString Text; COLOR4D color; int name_orientation; wxPoint pos_sheetname,pos_filename; wxPoint pos = m_pos + aOffset; int lineWidth = GetPenSize(); EDA_RECT* clipbox = aPanel? aPanel->GetClipBox() : NULL; if( aColor != COLOR4D::UNSPECIFIED ) color = aColor; else color = GetLayerColor( m_Layer ); GRSetDrawMode( aDC, aDrawMode ); GRRect( clipbox, aDC, pos.x, pos.y, pos.x + m_size.x, pos.y + m_size.y, lineWidth, color ); pos_sheetname = GetSheetNamePosition() + aOffset; pos_filename = GetFileNamePosition() + aOffset; if( IsVerticalOrientation() ) name_orientation = TEXT_ANGLE_VERT; else name_orientation = TEXT_ANGLE_HORIZ; /* Draw text : SheetName */ if( aColor != COLOR4D::UNSPECIFIED ) txtcolor = aColor; else txtcolor = GetLayerColor( LAYER_SHEETNAME ); Text = wxT( "Sheet: " ) + m_name; DrawGraphicText( clipbox, aDC, pos_sheetname, txtcolor, Text, name_orientation, wxSize( m_sheetNameSize, m_sheetNameSize ), GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_BOTTOM, lineWidth, false, false ); /* Draw text : FileName */ if( aColor != COLOR4D::UNSPECIFIED ) txtcolor = aColor; else txtcolor = GetLayerColor( LAYER_SHEETFILENAME ); Text = wxT( "File: " ) + m_fileName; DrawGraphicText( clipbox, aDC, pos_filename, txtcolor, Text, name_orientation, wxSize( m_fileNameSize, m_fileNameSize ), GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_TOP, lineWidth, false, false ); /* Draw text : SheetLabel */ for( SCH_SHEET_PIN& sheetPin : m_pins ) { if( !sheetPin.IsMoving() ) sheetPin.Draw( aPanel, aDC, aOffset, aDrawMode, aColor ); } #if 0 // Only for testing purposes, draw the component bounding box EDA_RECT boundingBox = GetBoundingBox(); GRRect( aPanel->GetClipBox(), aDC, boundingBox, 0, BROWN ); GRFilledCircle( aPanel->GetClipBox(), aDC, m_pos.x, m_pos.y, 10, 0, color, color ); #endif }
/** * Function DrawBasicShape * Draw the primitive shape for flashed items. */ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent, EDA_RECT* aClipBox, wxDC* aDC, EDA_COLOR_T aColor, EDA_COLOR_T aAltColor, wxPoint aShapePos, bool aFilledShape ) { static std::vector<wxPoint> polybuffer; // create a static buffer to avoid a lot of memory reallocation polybuffer.clear(); wxPoint curPos = aShapePos; D_CODE* tool = aParent->GetDcodeDescr(); double rotation; if( mapExposure( aParent ) == false ) { EXCHG(aColor, aAltColor); } switch( primitive_id ) { case AMP_CIRCLE: // Circle, given diameter and position { /* Generated by an aperture macro declaration like: * "1,1,0.3,0.5, 1.0*" * type (1), exposure, diameter, pos.x, pos.y * type is not stored in parameters list, so the first parameter is exposure */ curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric ); curPos = aParent->GetABPosition( curPos ); int radius = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ) / 2; if( !aFilledShape ) GRCircle( aClipBox, aDC, curPos, radius, 0, aColor ); else GRFilledCircle( aClipBox, aDC, curPos, radius, aColor ); } break; case AMP_LINE2: case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation) { /* Generated by an aperture macro declaration like: * "2,1,0.3,0,0, 0.5, 1.0,-135*" * type (2), exposure, width, start.x, start.y, end.x, end.y, rotation * type is not stored in parameters list, so the first parameter is exposure */ ConvertShapeToPolygon( aParent, polybuffer ); // shape rotation: rotation = params[6].GetValue( tool ) * 10.0; if( rotation != 0) { for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) RotatePoint( &polybuffer[ii], -rotation ); } // Move to current position: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); } break; case AMP_LINE_CENTER: { /* Generated by an aperture macro declaration like: * "21,1,0.3,0.03,0,0,-135*" * type (21), exposure, ,width, height, center pos.x, center pos.y, rotation * type is not stored in parameters list, so the first parameter is exposure */ ConvertShapeToPolygon( aParent, polybuffer ); // shape rotation: rotation = params[5].GetValue( tool ) * 10.0; if( rotation != 0 ) { for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) RotatePoint( &polybuffer[ii], -rotation ); } // Move to current position: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); } break; case AMP_LINE_LOWER_LEFT: { /* Generated by an aperture macro declaration like: * "22,1,0.3,0.03,0,0,-135*" * type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation * type is not stored in parameters list, so the first parameter is exposure */ ConvertShapeToPolygon( aParent, polybuffer ); // shape rotation: rotation = params[5].GetValue( tool ) * 10.0; if( rotation != 0) { for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) RotatePoint( &polybuffer[ii], -rotation ); } // Move to current position: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); } break; case AMP_THERMAL: { /* Generated by an aperture macro declaration like: * "7, 0,0,1.0,0.3,0.01,-13*" * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation * type is not stored in parameters list, so the first parameter is center.x */ curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), m_GerbMetric ); ConvertShapeToPolygon( aParent, polybuffer ); // shape rotation: rotation = params[5].GetValue( tool ) * 10.0; // Because a thermal shape has 4 identical sub-shapes, only one is created in polybuffer. // We must draw 4 sub-shapes rotated by 90 deg std::vector<wxPoint> subshape_poly; for( int ii = 0; ii < 4; ii++ ) { subshape_poly = polybuffer; double sub_rotation = rotation + 900 * ii; for( unsigned jj = 0; jj < subshape_poly.size(); jj++ ) RotatePoint( &subshape_poly[jj], -sub_rotation ); // Move to current position: for( unsigned jj = 0; jj < subshape_poly.size(); jj++ ) { subshape_poly[jj] += curPos; subshape_poly[jj] = aParent->GetABPosition( subshape_poly[jj] ); } GRClosedPoly( aClipBox, aDC, subshape_poly.size(), &subshape_poly[0], true, aAltColor, aAltColor ); } } break; case AMP_MOIRE: // A cross hair with n concentric circles { curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), m_GerbMetric ); /* Generated by an aperture macro declaration like: * "6,0,0,0.125,.01,0.01,3,0.003,0.150,0" * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness, crosshaire len, rotation * type is not stored in parameters list, so the first parameter is pos.x */ int outerDiam = scaletoIU( params[2].GetValue( tool ), m_GerbMetric ); int penThickness = scaletoIU( params[3].GetValue( tool ), m_GerbMetric ); int gap = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ); int numCircles = KiROUND( params[5].GetValue( tool ) ); // Draw circles: wxPoint center = aParent->GetABPosition( curPos ); // adjust outerDiam by this on each nested circle int diamAdjust = (gap + penThickness); //*2; //Should we use * 2 ? for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust ) { if( outerDiam <= 0 ) break; if( !aFilledShape ) { // draw the border of the pen's path using two circles, each as narrow as possible GRCircle( aClipBox, aDC, center, outerDiam / 2, 0, aColor ); GRCircle( aClipBox, aDC, center, outerDiam / 2 - penThickness, 0, aColor ); } else // Filled mode { GRCircle( aClipBox, aDC, center, (outerDiam - penThickness) / 2, penThickness, aColor ); } } // Draw the cross: ConvertShapeToPolygon( aParent, polybuffer ); rotation = params[8].GetValue( tool ) * 10.0; for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { // shape rotation: RotatePoint( &polybuffer[ii], -rotation ); // Move to current position: polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); } break; case AMP_OUTLINE: { /* Generated by an aperture macro declaration like: * "4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25" * type(4), exposure, corners count, corner1.x, corner.1y, ..., rotation * type is not stored in parameters list, so the first parameter is exposure */ int numPoints = (int) params[1].GetValue( tool ); rotation = params[numPoints * 2 + 4].GetValue( tool ) * 10.0; wxPoint pos; // Read points. numPoints does not include the starting point, so add 1. for( int i = 0; i<numPoints + 1; ++i ) { int jj = i * 2 + 2; pos.x = scaletoIU( params[jj].GetValue( tool ), m_GerbMetric ); pos.y = scaletoIU( params[jj + 1].GetValue( tool ), m_GerbMetric ); polybuffer.push_back(pos); } // rotate polygon and move it to the actual position // shape rotation: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { RotatePoint( &polybuffer[ii], -rotation ); } // Move to current position: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); } break; case AMP_POLYGON: // Is a regular polygon /* Generated by an aperture macro declaration like: * "5,1,0.6,0,0,0.5,25" * type(5), exposure, vertices count, pox.x, pos.y, diameter, rotation * type is not stored in parameters list, so the first parameter is exposure */ curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric ); // Creates the shape: ConvertShapeToPolygon( aParent, polybuffer ); // rotate polygon and move it to the actual position rotation = params[5].GetValue( tool ) * 10.0; for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { RotatePoint( &polybuffer[ii], -rotation ); polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); break; case AMP_EOF: // not yet supported, waiting for you. break; case AMP_UNKNOWN: default: DBG( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) ); break; } }
void Trace_Segment(WinEDA_DrawPanel * panel, wxDC * DC, TRACK* track, int draw_mode) /***********************************************************************************/ /* routine de trace de 1 segment de piste. Parametres : pt_piste = adresse de la description de la piste en buflib draw_mode = mode ( GR_XOR, GR_OR..) */ { int l_piste; int color; int zoom; int rayon; int fillopt; static bool show_err; color = g_DesignSettings.m_LayerColor[track->m_Layer]; if(color & ITEM_NOT_SHOW ) return ; zoom = panel->GetZoom(); GRSetDrawMode(DC, draw_mode); if( draw_mode & GR_SURBRILL) { if( draw_mode & GR_AND) color &= ~HIGHT_LIGHT_FLAG; else color |= HIGHT_LIGHT_FLAG; } if ( color & HIGHT_LIGHT_FLAG) color = ColorRefs[color & MASKCOLOR].m_LightColor; rayon = l_piste = track->m_Width >> 1; fillopt = DisplayOpt.DisplayPcbTrackFill ? FILLED : SKETCH; switch (track->m_Shape) { case S_CIRCLE: rayon = (int)hypot((double)(track->m_End.x-track->m_Start.x), (double)(track->m_End.y-track->m_Start.y) ); if ( (l_piste/zoom) < L_MIN_DESSIN) { GRCircle(&panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y, rayon , color) ; } if( fillopt == SKETCH) { GRCircle(&panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y, rayon-l_piste, color); GRCircle(&panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y, rayon+l_piste, color); } else { GRCircle(&panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y, rayon, track->m_Width,color); } break; case S_ARC: { if( fillopt == SKETCH) { GRArc1(&panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y, track->m_End.x, track->m_End.y, track->m_Param, track->m_Sous_Netcode, color); } else { GRArc1(&panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y, track->m_End.x, track->m_End.y, track->m_Param,track->m_Sous_Netcode, track->m_Width, color); } } break; case S_SPOT_CIRCLE: fillopt = DisplayOpt.DisplayPadFill ? FILLED : SKETCH; if ( (rayon/zoom) < L_MIN_DESSIN) { GRCircle(&panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y, rayon , color) ; } else if( fillopt == SKETCH ) { GRCircle(&panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y, rayon, color); } else { GRFilledCircle(&panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y, rayon, color, color); } break; case S_SPOT_RECT: case S_RECT: fillopt = DisplayOpt.DisplayPadFill ? FILLED : SKETCH; if ( (l_piste/zoom) < L_MIN_DESSIN) { GRLine(&panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y, track->m_End.x, track->m_End.y, color); } else if( fillopt == SKETCH ) { GRRect(&panel->m_ClipBox, DC, track->m_Start.x - l_piste, track->m_Start.y - l_piste, track->m_End.x + l_piste, track->m_End.y + l_piste, color) ; } else { GRFilledRect(&panel->m_ClipBox, DC, track->m_Start.x - l_piste, track->m_Start.y - l_piste, track->m_End.x + l_piste, track->m_End.y + l_piste, color, color) ; } break; case S_SPOT_OVALE: fillopt = DisplayOpt.DisplayPadFill ? FILLED : SKETCH; case S_SEGMENT: if ( (l_piste/zoom) < L_MIN_DESSIN) { GRLine(&panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y, track->m_End.x, track->m_End.y, color); break; } if( fillopt == SKETCH ) { GRCSegm(&panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y, track->m_End.x, track->m_End.y, track->m_Width, color) ; } else { GRFillCSegm(&panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y, track->m_End.x, track->m_End.y, track->m_Width, color) ; } break; default: if ( ! show_err ) { DisplayError(panel, wxT("Trace_Segment() type error")); show_err = TRUE; } break; } }
void VIA::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, const wxPoint& aOffset ) { int radius; LAYER_NUM curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer; int fillvia = 0; PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) panel->GetParent(); PCB_SCREEN* screen = frame->GetScreen(); if( frame->m_DisplayViaFill == FILLED ) fillvia = 1; GRSetDrawMode( aDC, aDrawMode ); BOARD * brd = GetBoard( ); EDA_COLOR_T color = brd->GetVisibleElementColor(VIAS_VISIBLE + GetViaType()); if( brd->IsElementVisible( PCB_VISIBLE(VIAS_VISIBLE + GetViaType()) ) == false && ( color & HIGHLIGHT_FLAG ) != HIGHLIGHT_FLAG ) return; if( DisplayOpt.ContrastModeDisplay ) { if( !IsOnLayer( curr_layer ) ) ColorTurnToDarkDarkGray( &color ); } if( aDrawMode & GR_HIGHLIGHT ) ColorChangeHighlightFlag( &color, !(aDrawMode & GR_AND) ); ColorApplyHighlightFlag( &color ); SetAlpha( &color, 150 ); radius = m_Width >> 1; // for small via size on screen (radius < 4 pixels) draw a simplified shape int radius_in_pixels = aDC->LogicalToDeviceXRel( radius ); bool fast_draw = false; // Vias are drawn as a filled circle or a double circle. The hole will be drawn later int drill_radius = GetDrillValue() / 2; int inner_radius = radius - aDC->DeviceToLogicalXRel( 2 ); if( radius_in_pixels < MIN_VIA_DRAW_SIZE ) { fast_draw = true; fillvia = false; } if( fillvia ) { GRFilledCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius, color ); } else { GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius, 0, color ); if ( fast_draw ) return; GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, inner_radius, 0, color ); } // Draw the via hole if the display option allows it if( DisplayOpt.m_DisplayViaMode != VIA_HOLE_NOT_SHOW ) { // Display all drill holes requested or Display non default holes requested if( (DisplayOpt.m_DisplayViaMode == ALL_VIA_HOLE_SHOW) || ( (drill_radius > 0 ) && !IsDrillDefault() ) ) { if( fillvia ) { bool blackpenstate = false; if( screen->m_IsPrinting ) { blackpenstate = GetGRForceBlackPenState(); GRForceBlackPen( false ); color = WHITE; } else { color = BLACK; // or DARKGRAY; } if( (aDrawMode & GR_XOR) == 0) GRSetDrawMode( aDC, GR_COPY ); if( aDC->LogicalToDeviceXRel( drill_radius ) > MIN_DRAW_WIDTH ) // Draw hole if large enough. GRFilledCircle( panel->GetClipBox(), aDC, m_Start.x + aOffset.x, m_Start.y + aOffset.y, drill_radius, 0, color, color ); if( screen->m_IsPrinting ) GRForceBlackPen( blackpenstate ); } else { if( drill_radius < inner_radius ) // We can show the via hole GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, drill_radius, 0, color ); } } } if( ShowClearance( this ) ) { GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius + GetClearance(), 0, color ); } // for Micro Vias, draw a partial cross : X on component layer, or + on copper layer // (so we can see 2 superimposed microvias ): if( GetViaType() == VIA_MICROVIA ) { int ax, ay, bx, by; if( IsOnLayer( LAYER_N_BACK ) ) { ax = radius; ay = 0; bx = drill_radius; by = 0; } else { ax = ay = (radius * 707) / 1000; bx = by = (drill_radius * 707) / 1000; } /* lines | or \ */ GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax, m_Start.y + aOffset.y - ay, m_Start.x + aOffset.x - bx, m_Start.y + aOffset.y - by, 0, color ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x + bx, m_Start.y + aOffset.y + by, m_Start.x + aOffset.x + ax, m_Start.y + aOffset.y + ay, 0, color ); // lines - or / GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x + ay, m_Start.y + aOffset.y - ax, m_Start.x + aOffset.x + by, m_Start.y + aOffset.y - bx, 0, color ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - by, m_Start.y + aOffset.y + bx, m_Start.x + aOffset.x - ay, m_Start.y + aOffset.y + ax, 0, color ); } // for Buried Vias, draw a partial line : orient depending on layer pair // (so we can see superimposed buried vias ): if( GetViaType() == VIA_BLIND_BURIED ) { int ax = 0, ay = radius, bx = 0, by = drill_radius; LAYER_NUM layer_top, layer_bottom; ( (VIA*) this )->LayerPair( &layer_top, &layer_bottom ); // lines for the top layer RotatePoint( &ax, &ay, layer_top * 3600.0 / brd->GetCopperLayerCount( ) ); RotatePoint( &bx, &by, layer_top * 3600.0 / brd->GetCopperLayerCount( ) ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax, m_Start.y + aOffset.y - ay, m_Start.x + aOffset.x - bx, m_Start.y + aOffset.y - by, 0, color ); // lines for the bottom layer ax = 0; ay = radius; bx = 0; by = drill_radius; RotatePoint( &ax, &ay, layer_bottom * 3600.0 / brd->GetCopperLayerCount( ) ); RotatePoint( &bx, &by, layer_bottom * 3600.0 / brd->GetCopperLayerCount( ) ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax, m_Start.y + aOffset.y - ay, m_Start.x + aOffset.x - bx, m_Start.y + aOffset.y - by, 0, color ); } // Display the short netname: if( GetNetCode() == NETINFO_LIST::UNCONNECTED ) return; if( DisplayOpt.DisplayNetNamesMode == 0 || DisplayOpt.DisplayNetNamesMode == 1 ) return; NETINFO_ITEM* net = GetNet(); if( net == NULL ) return; int len = net->GetShortNetname().Len(); if( len > 0 ) { // calculate a good size for the text int tsize = m_Width / len; if( aDC->LogicalToDeviceXRel( tsize ) >= MIN_TEXT_SIZE ) { tsize = (tsize * 7) / 10; // small reduction to give a better look, inside via if( (aDrawMode & GR_XOR) == 0 ) GRSetDrawMode( aDC, GR_COPY ); EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL; DrawGraphicHaloText( clipbox, aDC, m_Start, color, WHITE, BLACK, net->GetShortNetname(), 0, wxSize( tsize, tsize ), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, tsize / 7, false, false ); } } }
void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo ) { wxPoint coord[4]; double angle = m_Orient; int seg_width; GRSetDrawMode( aDC, aDrawInfo.m_DrawMode ); // calculate pad shape position : wxPoint shape_pos = ShapePos() - aDrawInfo.m_Offset; wxSize halfsize = m_Size; halfsize.x >>= 1; halfsize.y >>= 1; switch( GetShape() ) { case PAD_CIRCLE: if( aDrawInfo.m_ShowPadFilled ) GRFilledCircle( aClipBox, aDC, shape_pos.x, shape_pos.y, halfsize.x + aDrawInfo.m_Mask_margin.x, 0, aDrawInfo.m_Color, aDrawInfo.m_Color ); else GRCircle( aClipBox, aDC, shape_pos.x, shape_pos.y, halfsize.x + aDrawInfo.m_Mask_margin.x, m_PadSketchModePenSize, aDrawInfo.m_Color ); if( aDrawInfo.m_PadClearance ) { GRCircle( aClipBox, aDC, shape_pos.x, shape_pos.y, halfsize.x + aDrawInfo.m_PadClearance, 0, aDrawInfo.m_Color ); } break; case PAD_OVAL: { wxPoint segStart, segEnd; seg_width = BuildSegmentFromOvalShape(segStart, segEnd, angle, aDrawInfo.m_Mask_margin); segStart += shape_pos; segEnd += shape_pos; if( aDrawInfo.m_ShowPadFilled ) { GRFillCSegm( aClipBox, aDC, segStart.x, segStart.y, segEnd.x, segEnd.y, seg_width, aDrawInfo.m_Color ); } else { GRCSegm( aClipBox, aDC, segStart.x, segStart.y, segEnd.x, segEnd.y, seg_width, m_PadSketchModePenSize, aDrawInfo.m_Color ); } // Draw the clearance line if( aDrawInfo.m_PadClearance ) { seg_width += 2 * aDrawInfo.m_PadClearance; GRCSegm( aClipBox, aDC, segStart.x, segStart.y, segEnd.x, segEnd.y, seg_width, aDrawInfo.m_Color ); } } break; case PAD_RECT: case PAD_TRAPEZOID: BuildPadPolygon( coord, aDrawInfo.m_Mask_margin, angle ); for( int ii = 0; ii < 4; ii++ ) coord[ii] += shape_pos; GRClosedPoly( aClipBox, aDC, 4, coord, aDrawInfo.m_ShowPadFilled, aDrawInfo.m_ShowPadFilled ? 0 : m_PadSketchModePenSize, aDrawInfo.m_Color, aDrawInfo.m_Color ); if( aDrawInfo.m_PadClearance ) { BuildPadPolygon( coord, wxSize( aDrawInfo.m_PadClearance, aDrawInfo.m_PadClearance ), angle ); for( int ii = 0; ii < 4; ii++ ) coord[ii] += shape_pos; GRClosedPoly( aClipBox, aDC, 4, coord, 0, aDrawInfo.m_Color, aDrawInfo.m_Color ); } break; default: break; } // Draw the pad hole wxPoint holepos = m_Pos - aDrawInfo.m_Offset; int hole = m_Drill.x >> 1; bool drawhole = hole > 0; if( !aDrawInfo.m_ShowPadFilled && !aDrawInfo.m_ShowNotPlatedHole ) drawhole = false; if( drawhole ) { bool blackpenstate = false; if( aDrawInfo.m_IsPrinting ) { blackpenstate = GetGRForceBlackPenState(); GRForceBlackPen( false ); aDrawInfo.m_HoleColor = WHITE; } if( aDrawInfo.m_DrawMode != GR_XOR ) GRSetDrawMode( aDC, GR_COPY ); else GRSetDrawMode( aDC, GR_XOR ); EDA_COLOR_T hole_color = aDrawInfo.m_HoleColor; if( aDrawInfo. m_ShowNotPlatedHole ) // Draw a specific hole color hole_color = aDrawInfo.m_NPHoleColor; switch( GetDrillShape() ) { case PAD_DRILL_CIRCLE: if( aDC->LogicalToDeviceXRel( hole ) > MIN_DRAW_WIDTH ) GRFilledCircle( aClipBox, aDC, holepos.x, holepos.y, hole, 0, hole_color, hole_color ); break; case PAD_DRILL_OBLONG: { wxPoint drl_start, drl_end; GetOblongDrillGeometry( drl_start, drl_end, seg_width ); GRFilledSegment( aClipBox, aDC, holepos + drl_start, holepos + drl_end, seg_width, hole_color ); } break; default: break; } if( aDrawInfo.m_IsPrinting ) GRForceBlackPen( blackpenstate ); } GRSetDrawMode( aDC, aDrawInfo.m_DrawMode ); // Draw "No connect" ( / or \ or cross X ) if necessary if( GetNetCode() == 0 && aDrawInfo.m_ShowNCMark ) { int dx0 = std::min( halfsize.x, halfsize.y ); EDA_COLOR_T nc_color = BLUE; if( m_layerMask[F_Cu] ) /* Draw \ */ GRLine( aClipBox, aDC, holepos.x - dx0, holepos.y - dx0, holepos.x + dx0, holepos.y + dx0, 0, nc_color ); if( m_layerMask[B_Cu] ) // Draw / GRLine( aClipBox, aDC, holepos.x + dx0, holepos.y - dx0, holepos.x - dx0, holepos.y + dx0, 0, nc_color ); } if( aDrawInfo.m_DrawMode != GR_XOR ) GRSetDrawMode( aDC, GR_COPY ); else GRSetDrawMode( aDC, GR_XOR ); // Draw the pad number if( !aDrawInfo.m_Display_padnum && !aDrawInfo.m_Display_netname ) return; wxPoint tpos0 = shape_pos; // Position of the centre of text wxPoint tpos = tpos0; wxSize AreaSize; // size of text area, normalized to AreaSize.y < AreaSize.x int shortname_len = 0; if( aDrawInfo.m_Display_netname ) shortname_len = GetShortNetname().Len(); if( GetShape() == PAD_CIRCLE ) angle = 0; AreaSize = m_Size; if( m_Size.y > m_Size.x ) { angle += 900; AreaSize.x = m_Size.y; AreaSize.y = m_Size.x; } if( shortname_len > 0 ) // if there is a netname, provides room to display this netname { AreaSize.y /= 2; // Text used only the upper area of the // pad. The lower area displays the net name tpos.y -= AreaSize.y / 2; } // Calculate the position of text, that is the middle point of the upper // area of the pad RotatePoint( &tpos, shape_pos, angle ); // Draw text with an angle between -90 deg and + 90 deg double t_angle = angle; NORMALIZE_ANGLE_90( t_angle ); /* Note: in next calculations, texte size is calculated for 3 or more * chars. Of course, pads numbers and nets names can have less than 3 * chars. but after some tries, i found this is gives the best look */ #define MIN_CHAR_COUNT 3 wxString buffer; int tsize; EDA_RECT* clipBox = aDrawInfo.m_DrawPanel? aDrawInfo.m_DrawPanel->GetClipBox() : NULL; if( aDrawInfo.m_Display_padnum ) { StringPadName( buffer ); int numpad_len = buffer.Len(); numpad_len = std::max( numpad_len, MIN_CHAR_COUNT ); tsize = std::min( AreaSize.y, AreaSize.x / numpad_len ); if( aDC->LogicalToDeviceXRel( tsize ) >= MIN_TEXT_SIZE ) // Not drawable when size too small. { // tsize reserve room for marges and segments thickness tsize = ( tsize * 7 ) / 10; DrawGraphicHaloText( clipBox, aDC, tpos, aDrawInfo.m_Color, BLACK, WHITE, buffer, t_angle, wxSize( tsize , tsize ), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, tsize / 7, false, false ); } } // display the short netname, if exists if( shortname_len == 0 ) return; shortname_len = std::max( shortname_len, MIN_CHAR_COUNT ); tsize = std::min( AreaSize.y, AreaSize.x / shortname_len ); if( aDC->LogicalToDeviceXRel( tsize ) >= MIN_TEXT_SIZE ) // Not drawable in size too small. { tpos = tpos0; if( aDrawInfo.m_Display_padnum ) tpos.y += AreaSize.y / 2; RotatePoint( &tpos, shape_pos, angle ); // tsize reserve room for marges and segments thickness tsize = ( tsize * 7 ) / 10; DrawGraphicHaloText( clipBox, aDC, tpos, aDrawInfo.m_Color, BLACK, WHITE, GetShortNetname(), t_angle, wxSize( tsize, tsize ), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, tsize / 7, false, false ); } }
void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo ) { wxPoint coord[4]; int delta_cx, delta_cy; int angle = m_Orient; int seg_width; GRSetDrawMode( aDC, aDrawInfo.m_DrawMode ); // calculate pad shape position : wxPoint shape_pos = ReturnShapePos() - aDrawInfo.m_Offset; wxSize halfsize = m_Size; halfsize.x >>= 1; halfsize.y >>= 1; switch( GetShape() ) { case PAD_CIRCLE: if( aDrawInfo.m_ShowPadFilled ) GRFilledCircle( aClipBox, aDC, shape_pos.x, shape_pos.y, halfsize.x + aDrawInfo.m_Mask_margin.x, 0, aDrawInfo.m_Color, aDrawInfo.m_Color ); else GRCircle( aClipBox, aDC, shape_pos.x, shape_pos.y, halfsize.x + aDrawInfo.m_Mask_margin.x, m_PadSketchModePenSize, aDrawInfo.m_Color ); if( aDrawInfo.m_PadClearance ) { GRCircle( aClipBox, aDC, shape_pos.x, shape_pos.y, halfsize.x + aDrawInfo.m_PadClearance, 0, aDrawInfo.m_Color ); } break; case PAD_OVAL: { wxPoint segStart, segEnd; seg_width = BuildSegmentFromOvalShape(segStart, segEnd, angle); segStart += shape_pos; segEnd += shape_pos; if( aDrawInfo.m_ShowPadFilled ) { GRFillCSegm( aClipBox, aDC, segStart.x, segStart.y, segEnd.x, segEnd.y, seg_width, aDrawInfo.m_Color ); } else { GRCSegm( aClipBox, aDC, segStart.x, segStart.y, segEnd.x, segEnd.y, seg_width, m_PadSketchModePenSize, aDrawInfo.m_Color ); } /* Draw the isolation line. */ if( aDrawInfo.m_PadClearance ) { seg_width += 2 * aDrawInfo.m_PadClearance; GRCSegm( aClipBox, aDC, segStart.x, segStart.y, segEnd.x, segEnd.y, seg_width, aDrawInfo.m_Color ); } } break; case PAD_RECT: case PAD_TRAPEZOID: BuildPadPolygon( coord, aDrawInfo.m_Mask_margin, angle ); for( int ii = 0; ii < 4; ii++ ) coord[ii] += shape_pos; GRClosedPoly( aClipBox, aDC, 4, coord, aDrawInfo.m_ShowPadFilled, aDrawInfo.m_ShowPadFilled ? 0 : m_PadSketchModePenSize, aDrawInfo.m_Color, aDrawInfo.m_Color ); if( aDrawInfo.m_PadClearance ) { BuildPadPolygon( coord, wxSize( aDrawInfo.m_PadClearance, aDrawInfo.m_PadClearance ), angle ); for( int ii = 0; ii < 4; ii++ ) coord[ii] += shape_pos; GRClosedPoly( aClipBox, aDC, 4, coord, 0, aDrawInfo.m_Color, aDrawInfo.m_Color ); } break; default: break; } /* Draw the pad hole */ wxPoint holepos = m_Pos - aDrawInfo.m_Offset; int hole = m_Drill.x >> 1; bool drawhole = hole > 0; if( !aDrawInfo.m_ShowPadFilled && !aDrawInfo. m_ShowNotPlatedHole ) drawhole = false; if( drawhole ) { bool blackpenstate = false; if( aDrawInfo.m_IsPrinting ) { blackpenstate = GetGRForceBlackPenState(); GRForceBlackPen( false ); aDrawInfo.m_HoleColor = g_DrawBgColor; } if( aDrawInfo.m_DrawMode != GR_XOR ) GRSetDrawMode( aDC, GR_COPY ); else GRSetDrawMode( aDC, GR_XOR ); int hole_color = aDrawInfo.m_HoleColor; if( aDrawInfo. m_ShowNotPlatedHole ) // Draw a specific hole color hole_color = aDrawInfo.m_NPHoleColor; switch( m_DrillShape ) { case PAD_CIRCLE: if( aDC->LogicalToDeviceXRel( hole ) > 1 ) GRFilledCircle( aClipBox, aDC, holepos.x, holepos.y, hole, 0, aDrawInfo.m_Color, hole_color ); break; case PAD_OVAL: halfsize.x = m_Drill.x >> 1; halfsize.y = m_Drill.y >> 1; if( m_Drill.x > m_Drill.y ) /* horizontal */ { delta_cx = halfsize.x - halfsize.y; delta_cy = 0; seg_width = m_Drill.y; } else /* vertical */ { delta_cx = 0; delta_cy = halfsize.y - halfsize.x; seg_width = m_Drill.x; } RotatePoint( &delta_cx, &delta_cy, angle ); GRFillCSegm( aClipBox, aDC, holepos.x + delta_cx, holepos.y + delta_cy, holepos.x - delta_cx, holepos.y - delta_cy, seg_width, hole_color ); break; default: break; } if( aDrawInfo.m_IsPrinting ) GRForceBlackPen( blackpenstate ); } GRSetDrawMode( aDC, aDrawInfo.m_DrawMode ); /* Draw "No connect" ( / or \ or cross X ) if necessary. : */ if( m_Netname.IsEmpty() && aDrawInfo.m_ShowNCMark ) { int dx0 = MIN( halfsize.x, halfsize.y ); int nc_color = BLUE; if( m_layerMask & LAYER_FRONT ) /* Draw \ */ GRLine( aClipBox, aDC, holepos.x - dx0, holepos.y - dx0, holepos.x + dx0, holepos.y + dx0, 0, nc_color ); if( m_layerMask & LAYER_BACK ) /* Draw / */ GRLine( aClipBox, aDC, holepos.x + dx0, holepos.y - dx0, holepos.x - dx0, holepos.y + dx0, 0, nc_color ); } /* Draw the pad number */ if( !aDrawInfo.m_Display_padnum && !aDrawInfo.m_Display_netname ) return; wxPoint tpos0 = shape_pos; // Position of the centre of text wxPoint tpos = tpos0; wxSize AreaSize; // size of text area, normalized to AreaSize.y < AreaSize.x int shortname_len = m_ShortNetname.Len(); if( !aDrawInfo.m_Display_netname ) shortname_len = 0; if( GetShape() == PAD_CIRCLE ) angle = 0; AreaSize = m_Size; if( m_Size.y > m_Size.x ) { angle += 900; AreaSize.x = m_Size.y; AreaSize.y = m_Size.x; } if( shortname_len > 0 ) // if there is a netname, provides room to display this netname { AreaSize.y /= 2; // Text used only the upper area of the // pad. The lower area displays the net name tpos.y -= AreaSize.y / 2; } // Calculate the position of text, that is the middle point of the upper // area of the pad RotatePoint( &tpos, shape_pos, angle ); /* Draw text with an angle between -90 deg and + 90 deg */ int t_angle = angle; NORMALIZE_ANGLE_90( t_angle ); /* Note: in next calculations, texte size is calculated for 3 or more * chars. Of course, pads numbers and nets names can have less than 3 * chars. but after some tries, i found this is gives the best look */ #define MIN_CHAR_COUNT 3 wxString buffer; int tsize; if( aDrawInfo.m_Display_padnum ) { ReturnStringPadName( buffer ); int numpad_len = buffer.Len(); numpad_len = MAX( numpad_len, MIN_CHAR_COUNT ); tsize = min( AreaSize.y, AreaSize.x / numpad_len ); #define CHAR_SIZE_MIN 5 if( aDC->LogicalToDeviceXRel( tsize ) >= CHAR_SIZE_MIN ) // Not drawable when size too small. { // tsize reserve room for marges and segments thickness tsize = (int) ( tsize * 0.8 ); DrawGraphicText( aDrawInfo.m_DrawPanel, aDC, tpos, WHITE, buffer, t_angle, wxSize( tsize, tsize ), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, tsize / 7, false, false ); } } // display the short netname, if exists if( shortname_len == 0 ) return; shortname_len = MAX( shortname_len, MIN_CHAR_COUNT ); tsize = min( AreaSize.y, AreaSize.x / shortname_len ); if( aDC->LogicalToDeviceXRel( tsize ) >= CHAR_SIZE_MIN ) // Not drawable in size too small. { tpos = tpos0; if( aDrawInfo.m_Display_padnum ) tpos.y += AreaSize.y / 2; RotatePoint( &tpos, shape_pos, angle ); // tsize reserve room for marges and segments thickness tsize = (int) ( tsize * 0.8 ); DrawGraphicText( aDrawInfo.m_DrawPanel, aDC, tpos, WHITE, m_ShortNetname, t_angle, wxSize( tsize, tsize ), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, tsize / 7, false, false ); } }
void VIA::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, const wxPoint& aOffset ) { wxCHECK_RET( panel != NULL, wxT( "VIA::Draw panel cannot be NULL." ) ); int radius; PCB_LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer; int fillvia = 0; PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) panel->GetParent(); PCB_SCREEN* screen = frame->GetScreen(); auto displ_opts = (PCB_DISPLAY_OPTIONS*)( frame->GetDisplayOptions() ); if( displ_opts->m_DisplayViaFill == FILLED ) fillvia = 1; GRSetDrawMode( aDC, aDrawMode ); BOARD * brd = GetBoard(); COLOR4D color = frame->Settings().Colors().GetItemColor( LAYER_VIAS + GetViaType() ); if( brd->IsElementVisible( LAYER_VIAS + GetViaType() ) == false && !( aDrawMode & GR_HIGHLIGHT ) ) return; // Only draw the via if at least one of the layers it crosses is being displayed if( !( brd->GetVisibleLayers() & GetLayerSet() ).any() ) return; if( displ_opts->m_ContrastModeDisplay ) { if( !IsOnLayer( curr_layer ) ) color = COLOR4D( DARKDARKGRAY ); } if( ( aDrawMode & GR_HIGHLIGHT ) && !( aDrawMode & GR_AND ) ) color.SetToLegacyHighlightColor(); color.a = 0.588; radius = m_Width >> 1; // for small via size on screen (radius < 4 pixels) draw a simplified shape int radius_in_pixels = aDC->LogicalToDeviceXRel( radius ); bool fast_draw = false; // Vias are drawn as a filled circle or a double circle. The hole will be drawn later int drill_radius = GetDrillValue() / 2; int inner_radius = radius - aDC->DeviceToLogicalXRel( 2 ); if( radius_in_pixels < MIN_VIA_DRAW_SIZE ) { fast_draw = true; fillvia = false; } if( fillvia ) { GRFilledCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius, color ); } else { GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius, 0, color ); if ( fast_draw ) return; GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, inner_radius, 0, color ); } if( fillvia ) { bool blackpenstate = false; if( screen->m_IsPrinting ) { blackpenstate = GetGRForceBlackPenState(); GRForceBlackPen( false ); color = WHITE; } else { color = BLACK; // or DARKGRAY; } if( (aDrawMode & GR_XOR) == 0) GRSetDrawMode( aDC, GR_COPY ); // Draw hole if the radius is > 1pixel. if( aDC->LogicalToDeviceXRel( drill_radius ) > 1 ) GRFilledCircle( panel->GetClipBox(), aDC, m_Start.x + aOffset.x, m_Start.y + aOffset.y, drill_radius, 0, color, color ); if( screen->m_IsPrinting ) GRForceBlackPen( blackpenstate ); } else { if( drill_radius < inner_radius ) // We can show the via hole GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, drill_radius, 0, color ); } if( ShowClearance( displ_opts, this ) ) { GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius + GetClearance(), 0, color ); } // for Micro Vias, draw a partial cross : X on component layer, or + on copper layer // (so we can see 2 superimposed microvias ): if( GetViaType() == VIA_MICROVIA ) { int ax, ay, bx, by; if( IsOnLayer( B_Cu ) ) { ax = radius; ay = 0; bx = drill_radius; by = 0; } else { ax = ay = (radius * 707) / 1000; bx = by = (drill_radius * 707) / 1000; } // lines '|' or '\' GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax, m_Start.y + aOffset.y - ay, m_Start.x + aOffset.x - bx, m_Start.y + aOffset.y - by, 0, color ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x + bx, m_Start.y + aOffset.y + by, m_Start.x + aOffset.x + ax, m_Start.y + aOffset.y + ay, 0, color ); // lines - or '/' GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x + ay, m_Start.y + aOffset.y - ax, m_Start.x + aOffset.x + by, m_Start.y + aOffset.y - bx, 0, color ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - by, m_Start.y + aOffset.y + bx, m_Start.x + aOffset.x - ay, m_Start.y + aOffset.y + ax, 0, color ); } // for Buried Vias, draw a partial line : orient depending on layer pair // (so we can see superimposed buried vias ): if( GetViaType() == VIA_BLIND_BURIED ) { int ax = 0, ay = radius, bx = 0, by = drill_radius; PCB_LAYER_ID layer_top, layer_bottom; LayerPair( &layer_top, &layer_bottom ); // lines for the top layer RotatePoint( &ax, &ay, layer_top * 3600.0 / brd->GetCopperLayerCount( ) ); RotatePoint( &bx, &by, layer_top * 3600.0 / brd->GetCopperLayerCount( ) ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax, m_Start.y + aOffset.y - ay, m_Start.x + aOffset.x - bx, m_Start.y + aOffset.y - by, 0, color ); // lines for the bottom layer ax = 0; ay = radius; bx = 0; by = drill_radius; RotatePoint( &ax, &ay, layer_bottom * 3600.0 / brd->GetCopperLayerCount( ) ); RotatePoint( &bx, &by, layer_bottom * 3600.0 / brd->GetCopperLayerCount( ) ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax, m_Start.y + aOffset.y - ay, m_Start.x + aOffset.x - bx, m_Start.y + aOffset.y - by, 0, color ); } // Display the short netname: if( GetNetCode() == NETINFO_LIST::UNCONNECTED ) return; if( displ_opts->m_DisplayNetNamesMode == 0 || displ_opts->m_DisplayNetNamesMode == 1 ) return; NETINFO_ITEM* net = GetNet(); if( net == NULL ) return; int len = net->GetShortNetname().Len(); if( len > 0 ) { // calculate a good size for the text int tsize = m_Width / len; if( aDC->LogicalToDeviceXRel( tsize ) >= MIN_TEXT_SIZE ) { tsize = (tsize * 7) / 10; // small reduction to give a better look, inside via if( (aDrawMode & GR_XOR) == 0 ) GRSetDrawMode( aDC, GR_COPY ); EDA_RECT* clipbox = panel->GetClipBox(); DrawGraphicHaloText( clipbox, aDC, m_Start, color, WHITE, BLACK, net->GetShortNetname(), 0, wxSize( tsize, tsize ), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, tsize / 7, false, false ); } } }