diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 380f88fbde..704def78cc 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -472,7 +472,6 @@ set( PCB_COMMON_SRCS ${CMAKE_SOURCE_DIR}/pcbnew/legacy_plugin.cpp ${CMAKE_SOURCE_DIR}/pcbnew/netlist_reader/netlist_reader.cpp ${CMAKE_SOURCE_DIR}/pcbnew/pad_custom_shape_functions.cpp - ${CMAKE_SOURCE_DIR}/pcbnew/pad_print_functions.cpp ${CMAKE_SOURCE_DIR}/pcbnew/pcb_display_options.cpp ${CMAKE_SOURCE_DIR}/pcbnew/pcb_draw_panel_gal.cpp ${CMAKE_SOURCE_DIR}/pcbnew/netlist_reader/pcb_netlist.cpp diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 60129ab239..91a65b90d4 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -226,6 +226,47 @@ void D_PAD::SetRoundRectCornerRadius( double aRadius ) } +/** + * Function BuildSegmentFromOvalShape + * Has meaning only for OVAL (and ROUND) pads. + * Build an equivalent segment having the same shape as the OVAL shape, + * aSegStart and aSegEnd are the ending points of the equivalent segment of the shape + * aRotation is the asked rotation of the segment (usually m_Orient) + */ +int D_PAD::BuildSegmentFromOvalShape( wxPoint& aSegStart, wxPoint& aSegEnd, double aRotation, + const wxSize& aMargin ) const +{ + int width; + + if( m_Size.y < m_Size.x ) // Build an horizontal equiv segment + { + int delta = ( m_Size.x - m_Size.y ) / 2; + aSegStart.x = -delta - aMargin.x; + aSegStart.y = 0; + aSegEnd.x = delta + aMargin.x; + aSegEnd.y = 0; + width = m_Size.y + ( aMargin.y * 2 ); + } + else // Vertical oval: build a vertical equiv segment + { + int delta = ( m_Size.y -m_Size.x ) / 2; + aSegStart.x = 0; + aSegStart.y = -delta - aMargin.y; + aSegEnd.x = 0; + aSegEnd.y = delta + aMargin.y; + width = m_Size.x + ( aMargin.x * 2 ); + } + + if( aRotation ) + { + RotatePoint( &aSegStart, aRotation); + RotatePoint( &aSegEnd, aRotation); + } + + return width; +} + + const EDA_RECT D_PAD::GetBoundingBox() const { EDA_RECT area; @@ -755,6 +796,150 @@ int D_PAD::GetThermalGap() const } +void D_PAD::BuildPadPolygon( wxPoint aCoord[4], wxSize aInflateValue, + double aRotation ) const +{ + wxSize delta; + wxSize halfsize; + + halfsize.x = m_Size.x >> 1; + halfsize.y = m_Size.y >> 1; + + switch( GetShape() ) + { + case PAD_SHAPE_RECT: + // For rectangular shapes, inflate is easy + halfsize += aInflateValue; + + // Verify if do not deflate more than than size + // Only possible for inflate negative values. + if( halfsize.x < 0 ) + halfsize.x = 0; + + if( halfsize.y < 0 ) + halfsize.y = 0; + break; + + case PAD_SHAPE_TRAPEZOID: + // Trapezoidal pad: verify delta values + delta.x = ( m_DeltaSize.x >> 1 ); + delta.y = ( m_DeltaSize.y >> 1 ); + + // be sure delta values are not to large + if( (delta.x < 0) && (delta.x <= -halfsize.y) ) + delta.x = -halfsize.y + 1; + + if( (delta.x > 0) && (delta.x >= halfsize.y) ) + delta.x = halfsize.y - 1; + + if( (delta.y < 0) && (delta.y <= -halfsize.x) ) + delta.y = -halfsize.x + 1; + + if( (delta.y > 0) && (delta.y >= halfsize.x) ) + delta.y = halfsize.x - 1; + break; + + default: // is used only for rect and trap. pads + return; + } + + // Build the basic rectangular or trapezoid shape + // delta is null for rectangular shapes + aCoord[0].x = -halfsize.x - delta.y; // lower left + aCoord[0].y = +halfsize.y + delta.x; + + aCoord[1].x = -halfsize.x + delta.y; // upper left + aCoord[1].y = -halfsize.y - delta.x; + + aCoord[2].x = +halfsize.x - delta.y; // upper right + aCoord[2].y = -halfsize.y + delta.x; + + aCoord[3].x = +halfsize.x + delta.y; // lower right + aCoord[3].y = +halfsize.y - delta.x; + + // Offsetting the trapezoid shape id needed + // It is assumed delta.x or/and delta.y == 0 + if( GetShape() == PAD_SHAPE_TRAPEZOID && (aInflateValue.x != 0 || aInflateValue.y != 0) ) + { + double angle; + wxSize corr; + + if( delta.y ) // lower and upper segment is horizontal + { + // Calculate angle of left (or right) segment with vertical axis + angle = atan2( (double) m_DeltaSize.y, (double) m_Size.y ); + + // left and right sides are moved by aInflateValue.x in their perpendicular direction + // We must calculate the corresponding displacement on the horizontal axis + // that is delta.x +- corr.x depending on the corner + corr.x = KiROUND( tan( angle ) * aInflateValue.x ); + delta.x = KiROUND( aInflateValue.x / cos( angle ) ); + + // Horizontal sides are moved up and down by aInflateValue.y + delta.y = aInflateValue.y; + + // corr.y = 0 by the constructor + } + else if( delta.x ) // left and right segment is vertical + { + // Calculate angle of lower (or upper) segment with horizontal axis + angle = atan2( (double) m_DeltaSize.x, (double) m_Size.x ); + + // lower and upper sides are moved by aInflateValue.x in their perpendicular direction + // We must calculate the corresponding displacement on the vertical axis + // that is delta.y +- corr.y depending on the corner + corr.y = KiROUND( tan( angle ) * aInflateValue.y ); + delta.y = KiROUND( aInflateValue.y / cos( angle ) ); + + // Vertical sides are moved left and right by aInflateValue.x + delta.x = aInflateValue.x; + + // corr.x = 0 by the constructor + } + else // the trapezoid is a rectangle + { + delta = aInflateValue; // this pad is rectangular (delta null). + } + + aCoord[0].x += -delta.x - corr.x; // lower left + aCoord[0].y += delta.y + corr.y; + + aCoord[1].x += -delta.x + corr.x; // upper left + aCoord[1].y += -delta.y - corr.y; + + aCoord[2].x += delta.x - corr.x; // upper right + aCoord[2].y += -delta.y + corr.y; + + aCoord[3].x += delta.x + corr.x; // lower right + aCoord[3].y += delta.y - corr.y; + + /* test coordinates and clamp them if the offset correction is too large: + * Note: if a coordinate is bad, the other "symmetric" coordinate is bad + * So when a bad coordinate is found, the 2 symmetric coordinates + * are set to the minimun value (0) + */ + + if( aCoord[0].x > 0 ) // lower left x coordinate must be <= 0 + aCoord[0].x = aCoord[3].x = 0; + + if( aCoord[1].x > 0 ) // upper left x coordinate must be <= 0 + aCoord[1].x = aCoord[2].x = 0; + + if( aCoord[0].y < 0 ) // lower left y coordinate must be >= 0 + aCoord[0].y = aCoord[1].y = 0; + + if( aCoord[3].y < 0 ) // lower right y coordinate must be >= 0 + aCoord[3].y = aCoord[2].y = 0; + } + + if( aRotation ) + { + for( int ii = 0; ii < 4; ii++ ) + RotatePoint( &aCoord[ii], aRotation ); + } +} + + void D_PAD::GetMsgPanelInfo( EDA_UNITS aUnits, std::vector& aList ) { MODULE* module; diff --git a/pcbnew/class_pad.h b/pcbnew/class_pad.h index f6ec6f63ca..7e09698dfd 100644 --- a/pcbnew/class_pad.h +++ b/pcbnew/class_pad.h @@ -59,30 +59,6 @@ namespace KIGFX class VIEW; } -// Helper class to store parameters used to draw a pad -class PAD_DRAWINFO -{ -public: - COLOR4D m_Color; // color used to draw the pad shape , from pad layers and - // visible layers - COLOR4D m_HoleColor; // color used to draw the pad hole - COLOR4D m_NPHoleColor; // color used to draw a pad Not Plated hole - COLOR4D m_NoNetMarkColor; // color used to draw a mark on pads having no net - int m_PadClearance; // clearance value, used to draw the pad area outlines - wxSize m_Mask_margin; // margin, used to draw solder paste when only one layer is shown - bool m_Display_padnum; // true to show pad number - bool m_Display_netname; // true to show net name - bool m_ShowPadFilled; // true to show pad as solid area, false to show pas in - // sketch mode - bool m_ShowNCMark; // true to show pad not connected mark - bool m_ShowNotPlatedHole; // true when the pad hole in not plated, to draw a specific - // pad shape - bool m_IsPrinting; // true to print, false to display on screen. - wxPoint m_Offset; // general draw offset - - PAD_DRAWINFO(); -}; - /** Helper class to handle a primitive (basic shape: polygon, segment, circle or arc) * to build a custom pad full shape from a set of primitives */ @@ -545,16 +521,6 @@ public: void SetThermalGap( int aGap ) { m_ThermalGap = aGap; } int GetThermalGap() const; - /** - * Function PrintShape - * basic function to print a pad. - *

- * This function is used by Print after calculation of parameters (color, ) final - * orientation transforms are set. - *

- */ - void PrintShape( wxDC* aDC, PAD_DRAWINFO& aDrawInfo ); - /** * Function BuildPadPolygon * Has meaning only for polygonal pads (trapezoid and rectangular) diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 36662503ff..699ee89085 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -318,81 +318,6 @@ bool ZONE_CONTAINER::IsOnLayer( PCB_LAYER_ID aLayer ) const } -void ZONE_CONTAINER::PrintFilledArea( PCB_BASE_FRAME* aFrame, wxDC* DC, const wxPoint& offset ) -{ - static std::vector CornersBuffer; - - BOARD* brd = GetBoard(); - COLOR4D color = Pgm().GetSettingsManager().GetColorSettings()->GetColor( GetLayer() ); - auto& displ_opts = aFrame->GetDisplayOptions(); - bool outline_mode = displ_opts.m_DisplayZonesMode == 2; - - if( DC == NULL ) - return; - - if( displ_opts.m_DisplayZonesMode == 1 ) // Do not show filled areas - return; - - if( m_FilledPolysList.IsEmpty() ) // Nothing to draw - return; - - if( brd->IsLayerVisible( GetLayer() ) == false ) - return; - - color.a = 0.588; - - for( int ic = 0; ic < m_FilledPolysList.OutlineCount(); ic++ ) - { - const SHAPE_LINE_CHAIN& path = m_FilledPolysList.COutline( ic ); - - CornersBuffer.clear(); - - wxPoint p0; - - for( int j = 0; j < path.PointCount(); j++ ) - { - const VECTOR2I& corner = path.CPoint( j ); - - wxPoint coord( corner.x + offset.x, corner.y + offset.y ); - - if( j == 0 ) - p0 = coord; - - CornersBuffer.push_back( coord ); - } - - CornersBuffer.push_back( p0 ); - - // Draw outlines: - int outline_thickness = GetFilledPolysUseThickness() ? GetMinThickness() : 0; - - if( ( outline_thickness > 1 ) || outline_mode ) - { - int ilim = CornersBuffer.size() - 1; - - for( int is = 0, ie = ilim; is <= ilim; ie = is, is++ ) - { - // Draw only basic outlines, not extra segments. - if( !displ_opts.m_DisplayPcbTrackFill || GetState( FORCE_SKETCH ) ) - { - GRCSegm( nullptr, DC, CornersBuffer[is], CornersBuffer[ie], - outline_thickness, color ); - } - else - { - GRFilledSegment( nullptr, DC, CornersBuffer[is], CornersBuffer[ie], - outline_thickness, color ); - } - } - } - - // Draw fill: - if( !outline_mode ) - GRPoly( nullptr, DC, CornersBuffer.size(), &CornersBuffer[0], true, 0, color, color ); - } -} - - const EDA_RECT ZONE_CONTAINER::GetBoundingBox() const { auto bb = m_Poly->BBox(); diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index 96fd24af73..54325cbd43 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -105,16 +105,6 @@ public: virtual LSET GetLayerSet() const override; - /** - * Function PrintFilledArea - * Draws the filled area for this zone (polygon list .m_FilledPolysList) - * @param aFrame = current Frame - * @param DC = current Device Context - * @param offset = Draw offset (usually wxPoint(0,0)) - * @param aDrawMode = GR_OR, GR_XOR, GR_COPY .. - */ - void PrintFilledArea( PCB_BASE_FRAME* aFrame, wxDC* DC, const wxPoint& offset = ZeroOffset ); - /** Function GetBoundingBox (virtual) * @return an EDA_RECT that is the bounding box of the zone outline */ diff --git a/pcbnew/dialogs/dialog_pad_properties.cpp b/pcbnew/dialogs/dialog_pad_properties.cpp index 912f94913b..f886e7e55e 100644 --- a/pcbnew/dialogs/dialog_pad_properties.cpp +++ b/pcbnew/dialogs/dialog_pad_properties.cpp @@ -255,7 +255,6 @@ void DIALOG_PAD_PROPERTIES::prepareCanvas() m_panelShowPadGal->GetViewControls()->EnableMousewheelPan( mousewheelPan ); m_panelShowPadGal->Show(); - m_panelShowPad->Hide(); KIGFX::VIEW* view = m_panelShowPadGal->GetView(); @@ -280,179 +279,6 @@ void DIALOG_PAD_PROPERTIES::prepareCanvas() } -void DIALOG_PAD_PROPERTIES::OnPaintShowPanel( wxPaintEvent& event ) -{ - wxPaintDC dc( m_panelShowPad ); - PAD_DRAWINFO drawInfo; - - COLOR4D color = COLOR4D::BLACK; - - if( m_dummyPad->GetLayerSet()[F_Cu] ) - color = m_parent->ColorSettings()->GetColor( LAYER_PAD_FR ); - - if( m_dummyPad->GetLayerSet()[B_Cu] ) - color = color.LegacyMix( m_parent->ColorSettings()->GetColor( LAYER_PAD_BK ) ); - - // What could happen: the pad color is *actually* black, or no copper was selected - if( color == BLACK ) - color = LIGHTGRAY; - - drawInfo.m_Color = color; - drawInfo.m_HoleColor = DARKGRAY; - drawInfo.m_Offset = m_dummyPad->GetPosition(); - drawInfo.m_Display_padnum = true; - drawInfo.m_Display_netname = true; - drawInfo.m_ShowPadFilled = !m_sketchPreview; - - if( m_dummyPad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED ) - drawInfo.m_ShowNotPlatedHole = true; - - // Shows the local pad clearance - drawInfo.m_PadClearance = m_dummyPad->GetLocalClearance(); - - wxSize dc_size = dc.GetSize(); - dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 ); - - // Calculate a suitable scale to fit the available draw area - int dim = m_dummyPad->GetBoundingRadius() *2; - - // Invalid x size. User could enter zero, or have deleted all text prior to - // entering a new value; this is also treated as zero. If dim is left at - // zero, the drawing scale is zero and we get a crash. - if( dim == 0 ) - { - // If drill size has been set, use that. Otherwise default to 1mm. - dim = m_dummyPad->GetDrillSize().x; - - if( dim == 0 ) - dim = Millimeter2iu( 1.0 ); - } - - if( m_dummyPad->GetLocalClearance() > 0 ) - dim += m_dummyPad->GetLocalClearance() * 2; - - double scale = (double) dc_size.x / dim; - - // If the pad is a circle, use the x size here instead. - int ysize; - - if( m_dummyPad->GetShape() == PAD_SHAPE_CIRCLE ) - ysize = m_dummyPad->GetSize().x; - else - ysize = m_dummyPad->GetSize().y; - - dim = ysize + std::abs( m_dummyPad->GetDelta().x ); - - // Invalid y size. See note about x size above. - if( dim == 0 ) - { - dim = m_dummyPad->GetDrillSize().y; - - if( dim == 0 ) - dim = Millimeter2iu( 0.1 ); - } - - if( m_dummyPad->GetLocalClearance() > 0 ) - dim += m_dummyPad->GetLocalClearance() * 2; - - double altscale = (double) dc_size.y / dim; - scale = std::min( scale, altscale ); - - // Give a margin - scale *= 0.7; - dc.SetUserScale( scale, scale ); - - GRResetPenAndBrush( &dc ); - m_dummyPad->PrintShape( &dc, drawInfo ); - - // draw selected primitives: - long select = m_listCtrlPrimitives->GetFirstSelected(); - - while( select >= 0 ) - { - PAD_CS_PRIMITIVE& primitive = m_primitives[select]; - - // The best way to calculate parameters to draw a primitive is to - // use a dummy DRAWSEGMENT and use its methods - // Note: in legacy canvas, the pad has the 0,0 position - DRAWSEGMENT dummySegment; - primitive.ExportTo( &dummySegment ); - dummySegment.Rotate( wxPoint( 0, 0), m_dummyPad->GetOrientation() ); - - switch( primitive.m_Shape ) - { - case S_SEGMENT: // usual segment : line with rounded ends - if( !m_sketchPreview ) - GRFilledSegment( NULL, &dc, dummySegment.GetStart(), dummySegment.GetEnd(), - primitive.m_Thickness, m_selectedColor ); - else - GRCSegm( NULL, &dc, dummySegment.GetStart(), dummySegment.GetEnd(), - primitive.m_Thickness, m_selectedColor ); - break; - - case S_ARC: // Arc with rounded ends - if( !m_sketchPreview ) - GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(), - dummySegment.GetCenter(), primitive.m_Thickness, m_selectedColor ); - else - { - GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(), - dummySegment.GetCenter(), 0, m_selectedColor ); -/* GRArc1( NULL, &dc, dummySegment.GetArcEnd(), dummySegment.GetArcStart(), - dummySegment.GetCenter() - primitive.m_Thickness, 0, m_selectedColor );*/ - } - break; - - case S_CIRCLE: // ring or circle - if( primitive.m_Thickness ) - { - if( !m_sketchPreview ) - GRCircle( nullptr, &dc, dummySegment.GetCenter(), primitive.m_Radius, - primitive.m_Thickness, m_selectedColor ); - else - { - GRCircle( nullptr, &dc, dummySegment.GetCenter(), - primitive.m_Radius + primitive.m_Thickness/2, 0, m_selectedColor ); - GRCircle( nullptr, &dc, dummySegment.GetCenter(), - primitive.m_Radius - primitive.m_Thickness/2, 0, m_selectedColor ); - } - } - else - { - if( !m_sketchPreview ) - GRFilledCircle( nullptr, &dc, dummySegment.GetCenter(), primitive.m_Radius, - m_selectedColor ); - else - GRCircle( nullptr, &dc, dummySegment.GetCenter(), primitive.m_Radius, 0, - m_selectedColor ); - } - break; - - case S_POLYGON: // polygon - { - std::vector poly = dummySegment.BuildPolyPointsList(); - GRClosedPoly( nullptr, &dc, poly.size(), &poly[0], !m_sketchPreview, - primitive.m_Thickness, m_selectedColor, m_selectedColor ); - } - break; - - default: - break; - } - - select = m_listCtrlPrimitives->GetNextSelected( select ); - } - - // Draw X and Y axis. This is particularly useful to show the - // reference position of pads with offset and no hole, or custom pad shapes - const int t = 0; // line thickness - GRLine( nullptr, &dc, -int( dc_size.x/scale ), 0, int( dc_size.x/scale ), 0, t, LIGHTBLUE ); - GRLine( nullptr, &dc, 0, -int( dc_size.y/scale ), 0, int( dc_size.y/scale ), t, LIGHTBLUE ); - - event.Skip(); -} - - void DIALOG_PAD_PROPERTIES::updateRoundRectCornerValues() { // Note: use m_tcCornerSizeRatio->ChangeValue() to avoid generating a wxEVT_TEXT event diff --git a/pcbnew/dialogs/dialog_pad_properties.h b/pcbnew/dialogs/dialog_pad_properties.h index c76d6fdc6b..239dc2ec01 100644 --- a/pcbnew/dialogs/dialog_pad_properties.h +++ b/pcbnew/dialogs/dialog_pad_properties.h @@ -125,7 +125,6 @@ private: void PadTypeSelected( wxCommandEvent& event ) override; void OnSetLayers( wxCommandEvent& event ) override; - void OnPaintShowPanel( wxPaintEvent& event ) override; // Called when corner setup value is changed for rounded rect pads void onCornerSizePercentChange( wxCommandEvent& event ) override; diff --git a/pcbnew/dialogs/dialog_pad_properties_base.cpp b/pcbnew/dialogs/dialog_pad_properties_base.cpp index 50d6348e0c..9bda88ae82 100644 --- a/pcbnew/dialogs/dialog_pad_properties_base.cpp +++ b/pcbnew/dialogs/dialog_pad_properties_base.cpp @@ -694,12 +694,6 @@ DIALOG_PAD_PROPERTIES_BASE::DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWind bSizerDisplayPad->Add( 0, 0, 1, wxEXPAND, 5 ); - m_panelShowPad = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxFULL_REPAINT_ON_RESIZE|wxBORDER_SIMPLE ); - m_panelShowPad->SetBackgroundColour( wxColour( 0, 0, 0 ) ); - m_panelShowPad->SetMinSize( wxSize( 280,-1 ) ); - - bSizerDisplayPad->Add( m_panelShowPad, 12, wxEXPAND|wxALL, 5 ); - m_panelShowPadGal = new PCB_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), wxDefaultSize, m_galOptions, EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO); m_panelShowPadGal->SetMinSize( wxSize( 280,-1 ) ); @@ -781,7 +775,6 @@ DIALOG_PAD_PROPERTIES_BASE::DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWind m_buttonAddShape->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onAddPrimitive ), NULL, this ); m_buttonDup->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onDuplicatePrimitive ), NULL, this ); m_buttonGeometry->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onGeometryTransform ), NULL, this ); - m_panelShowPad->Connect( wxEVT_PAINT, wxPaintEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnPaintShowPanel ), NULL, this ); m_cbShowPadOutline->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onChangePadMode ), NULL, this ); m_sdbSizerCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnCancel ), NULL, this ); } @@ -834,7 +827,6 @@ DIALOG_PAD_PROPERTIES_BASE::~DIALOG_PAD_PROPERTIES_BASE() m_buttonAddShape->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onAddPrimitive ), NULL, this ); m_buttonDup->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onDuplicatePrimitive ), NULL, this ); m_buttonGeometry->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onGeometryTransform ), NULL, this ); - m_panelShowPad->Disconnect( wxEVT_PAINT, wxPaintEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnPaintShowPanel ), NULL, this ); m_cbShowPadOutline->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::onChangePadMode ), NULL, this ); m_sdbSizerCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PAD_PROPERTIES_BASE::OnCancel ), NULL, this ); diff --git a/pcbnew/dialogs/dialog_pad_properties_base.fbp b/pcbnew/dialogs/dialog_pad_properties_base.fbp index 25623c06ff..95b704e401 100644 --- a/pcbnew/dialogs/dialog_pad_properties_base.fbp +++ b/pcbnew/dialogs/dialog_pad_properties_base.fbp @@ -8156,64 +8156,6 @@ 0 - - 5 - wxEXPAND|wxALL - 12 - - 1 - 1 - 1 - 1 - - - - - - 0,0,0 - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - 280,-1 - 1 - m_panelShowPad - 1 - - - protected - 1 - - Resizable - 1 - -1,-1 - - 0 - - - - wxFULL_REPAINT_ON_RESIZE|wxBORDER_SIMPLE - OnPaintShowPanel - - 5 wxEXPAND|wxALL @@ -8434,7 +8376,7 @@ - + 0 wxAUI_MGR_DEFAULT diff --git a/pcbnew/dialogs/dialog_pad_properties_base.h b/pcbnew/dialogs/dialog_pad_properties_base.h index c69d0b5639..4b0da196c8 100644 --- a/pcbnew/dialogs/dialog_pad_properties_base.h +++ b/pcbnew/dialogs/dialog_pad_properties_base.h @@ -185,7 +185,6 @@ class DIALOG_PAD_PROPERTIES_BASE : public DIALOG_SHIM wxButton* m_buttonGeometry; wxStaticText* m_parentInfoLine1; wxStaticText* m_parentInfoLine2; - wxPanel* m_panelShowPad; PCB_DRAW_PANEL_GAL* m_panelShowPadGal; KIGFX::GAL_DISPLAY_OPTIONS m_galOptions; wxCheckBox* m_cbShowPadOutline; @@ -213,7 +212,6 @@ class DIALOG_PAD_PROPERTIES_BASE : public DIALOG_SHIM virtual void onAddPrimitive( wxCommandEvent& event ) { event.Skip(); } virtual void onDuplicatePrimitive( wxCommandEvent& event ) { event.Skip(); } virtual void onGeometryTransform( wxCommandEvent& event ) { event.Skip(); } - virtual void OnPaintShowPanel( wxPaintEvent& event ) { event.Skip(); } virtual void onChangePadMode( wxCommandEvent& event ) { event.Skip(); } virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } diff --git a/pcbnew/pad_print_functions.cpp b/pcbnew/pad_print_functions.cpp deleted file mode 100644 index 78e14ea83e..0000000000 --- a/pcbnew/pad_print_functions.cpp +++ /dev/null @@ -1,621 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2017 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr - * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 2012 Wayne Stambaugh - * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include // for KiROUND -#include -#include -#include -#include -#include -#include - - -// Helper class to store parameters used to draw a pad -PAD_DRAWINFO::PAD_DRAWINFO() -{ - m_Color = BLACK; - m_HoleColor = BLACK; // could be DARKGRAY; - m_NPHoleColor = YELLOW; - m_NoNetMarkColor = BLUE; - m_PadClearance = 0; - m_Display_padnum = true; - m_Display_netname = true; - m_ShowPadFilled = true; - m_ShowNCMark = true; - m_ShowNotPlatedHole = false; - m_IsPrinting = false; -} - - -void D_PAD::PrintShape( wxDC* aDC, PAD_DRAWINFO& aDrawInfo ) -{ - #define SEGCOUNT 32 // number of segments to approximate a circle - wxPoint coord[12]; - double angle = m_Orient; - int seg_width; - - // 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_SHAPE_CIRCLE: - if( aDrawInfo.m_ShowPadFilled ) - GRFilledCircle( nullptr, aDC, shape_pos.x, shape_pos.y, - halfsize.x + aDrawInfo.m_Mask_margin.x, 0, - aDrawInfo.m_Color, aDrawInfo.m_Color ); - else - GRCircle( nullptr, aDC, shape_pos.x, shape_pos.y, - halfsize.x + aDrawInfo.m_Mask_margin.x, - m_PadSketchModePenSize, aDrawInfo.m_Color ); - - if( aDrawInfo.m_PadClearance ) - { - GRCircle( nullptr, aDC, shape_pos.x, shape_pos.y, - halfsize.x + aDrawInfo.m_PadClearance, 0, aDrawInfo.m_Color ); - } - - break; - - case PAD_SHAPE_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( nullptr, aDC, segStart.x, segStart.y, segEnd.x, segEnd.y, seg_width, - aDrawInfo.m_Color ); - } - else - { - GRCSegm( nullptr, 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( nullptr, aDC, segStart.x, segStart.y, segEnd.x, segEnd.y, seg_width, - aDrawInfo.m_Color ); - } - } - break; - - case PAD_SHAPE_RECT: - case PAD_SHAPE_TRAPEZOID: - BuildPadPolygon( coord, aDrawInfo.m_Mask_margin, angle ); - - for( int ii = 0; ii < 4; ii++ ) - coord[ii] += shape_pos; - - GRClosedPoly( nullptr, aDC, 4, coord, aDrawInfo.m_ShowPadFilled, - aDrawInfo.m_ShowPadFilled ? 0 : m_PadSketchModePenSize, - aDrawInfo.m_Color, aDrawInfo.m_Color ); - - if( aDrawInfo.m_PadClearance ) - { - SHAPE_POLY_SET outline; - TransformShapeWithClearanceToPolygon( outline, aDrawInfo.m_PadClearance ); - - // Draw the polygon: Inflate creates only one convex polygon - if( outline.OutlineCount() > 0 ) - { - SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); - - if( poly.PointCount() > 0 ) - { - GRClosedPoly( nullptr, aDC, poly.PointCount(), - (const wxPoint*) &poly.CPoint( 0 ), false, 0, aDrawInfo.m_Color, - aDrawInfo.m_Color ); - } - } - } - break; - - case PAD_SHAPE_CHAMFERED_RECT: - case PAD_SHAPE_ROUNDRECT: - { - // Use solder[Paste/Mask]size or pad size to build pad shape to draw - wxSize size( GetSize() ); - size += aDrawInfo.m_Mask_margin * 2; - int corner_radius = GetRoundRectCornerRadius( size ); - bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT; - - SHAPE_POLY_SET outline; - TransformRoundChamferedRectToPolygon( outline, shape_pos, size, GetOrientation(), - corner_radius, GetChamferRectRatio(), - doChamfer ? GetChamferPositions() : 0, - ARC_HIGH_DEF ); - - // Draw the polygon: Inflate creates only one convex polygon - bool filled = aDrawInfo.m_ShowPadFilled; - - SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); - - GRClosedPoly( nullptr, aDC, poly.PointCount(), (const wxPoint*) &poly.CPoint( 0 ), filled, - 0, aDrawInfo.m_Color, aDrawInfo.m_Color ); - - if( aDrawInfo.m_PadClearance ) - { - outline.RemoveAllContours(); - size = GetSize(); - size.x += aDrawInfo.m_PadClearance * 2; - size.y += aDrawInfo.m_PadClearance * 2; - corner_radius = GetRoundRectCornerRadius() + aDrawInfo.m_PadClearance; - - TransformRoundChamferedRectToPolygon( outline, shape_pos, size, GetOrientation(), - corner_radius, GetChamferRectRatio(), - doChamfer ? GetChamferPositions() : 0, - ARC_HIGH_DEF ); - - // Draw the polygon: Inflate creates only one convex polygon - SHAPE_LINE_CHAIN& clearance_poly = outline.Outline( 0 ); - - GRClosedPoly( nullptr, aDC, clearance_poly.PointCount(), - (const wxPoint*) &clearance_poly.CPoint( 0 ), false, 0, aDrawInfo.m_Color, - aDrawInfo.m_Color ); - } - } - break; - - case PAD_SHAPE_CUSTOM: - { - // The full shape has 2 items - // 1- The anchor pad: a round or rect pad located at pad position - // 2- The custom complex shape - // Note: The anchor pad shape is containing by the custom complex shape polygon - // The anchor pad is shown to help user to see where is the anchor, only in sketch mode - // (In filled mode, it is merged with the basic shapes) - wxPoint pad_pos = GetPosition() - aDrawInfo.m_Offset; - - // In sketch mode only: Draw the anchor pad: a round or rect pad - if( !aDrawInfo.m_ShowPadFilled ) - { - if( GetAnchorPadShape() == PAD_SHAPE_RECT ) - { - wxPoint poly[4]; - poly[0] = wxPoint( - halfsize.x, - halfsize.y ); - poly[1] = wxPoint( - halfsize.x, + halfsize.y ); - poly[2] = wxPoint( + halfsize.x, + halfsize.y ); - poly[3] = wxPoint( + halfsize.x, - halfsize.y ); - - for( int ii = 0; ii < 4; ++ii ) - { - RotatePoint( &poly[ii], m_Orient ); - poly[ii] += pad_pos; - } - - GRClosedPoly( nullptr, aDC, 4, poly, false, 0, aDrawInfo.m_Color, - aDrawInfo.m_Color ); - } - else - { - GRCircle( nullptr, aDC, pad_pos.x, pad_pos.y, halfsize.x, - m_PadSketchModePenSize, aDrawInfo.m_Color ); - } - } - - SHAPE_POLY_SET outline; // Will contain the corners in board coordinates - outline.Append( m_customShapeAsPolygon ); - CustomShapeAsPolygonToBoardPosition( &outline, pad_pos, GetOrientation() ); - - if( aDrawInfo.m_Mask_margin.x ) - { - int numSegs = GetArcToSegmentCount( aDrawInfo.m_Mask_margin.x, ARC_HIGH_DEF, 360.0 ); - outline.InflateWithLinkedHoles( - aDrawInfo.m_Mask_margin.x, numSegs, SHAPE_POLY_SET::PM_FAST ); - } - - // Draw the polygon: only one polygon is expected - // However we provide a multi polygon shape drawing - // ( can happen with CUSTOM pads and negative margins ) - for( int jj = 0; jj < outline.OutlineCount(); ++jj ) - { - auto& poly = outline.Outline( jj ); - - GRClosedPoly( nullptr, aDC, poly.PointCount(), (const wxPoint*) &poly.CPoint( 0 ), - aDrawInfo.m_ShowPadFilled, 0, aDrawInfo.m_Color, aDrawInfo.m_Color ); - } - - if( aDrawInfo.m_PadClearance ) - { - SHAPE_POLY_SET clearance_outline; - clearance_outline.Append( outline ); - - int numSegs = GetArcToSegmentCount( aDrawInfo.m_PadClearance, ARC_HIGH_DEF, 360.0 ); - clearance_outline.InflateWithLinkedHoles( - aDrawInfo.m_PadClearance, numSegs, SHAPE_POLY_SET::PM_FAST ); - - for( int jj = 0; jj < clearance_outline.OutlineCount(); ++jj ) - { - auto& poly = clearance_outline.Outline( jj ); - - if( poly.PointCount() > 0 ) - { - GRClosedPoly( nullptr, aDC, poly.PointCount(), - (const wxPoint*) &poly.CPoint( 0 ), false, 0, aDrawInfo.m_Color, - aDrawInfo.m_Color ); - } - } - } - - 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; - COLOR4D fillcolor = aDrawInfo.m_ShowNotPlatedHole? aDrawInfo.m_NPHoleColor : - aDrawInfo.m_HoleColor; - COLOR4D hole_color = fillcolor; - - fillcolor = COLOR4D::WHITE; - blackpenstate = GetGRForceBlackPenState(); - GRForceBlackPen( false ); - - if( blackpenstate ) - hole_color = COLOR4D::BLACK; - - switch( GetDrillShape() ) - { - case PAD_DRILL_SHAPE_CIRCLE: - if( aDC->LogicalToDeviceXRel( hole ) > 1 ) // hole is drawn if hole > 1pixel - GRFilledCircle( nullptr, aDC, holepos.x, holepos.y, hole, 0, hole_color, fillcolor ); - break; - - case PAD_DRILL_SHAPE_OBLONG: - { - wxPoint drl_start, drl_end; - GetOblongDrillGeometry( drl_start, drl_end, seg_width ); - drl_start += holepos; - drl_end += holepos; - GRFilledSegment( nullptr, aDC, drl_start, drl_end, seg_width, fillcolor ); - GRCSegm( nullptr, aDC, drl_start, drl_end, seg_width, hole_color ); - } - break; - - default: - break; - } - - if( aDrawInfo.m_IsPrinting ) - GRForceBlackPen( blackpenstate ); - } - - // Draw "No connect" ( / or \ or cross X ) if necessary - if( GetNetCode() == 0 && aDrawInfo.m_ShowNCMark ) - { - int dx0 = std::min( halfsize.x, halfsize.y ); - - if( m_layerMask[F_Cu] ) /* Draw \ */ - GRLine( nullptr, aDC, holepos.x - dx0, holepos.y - dx0, - holepos.x + dx0, holepos.y + dx0, 0, aDrawInfo.m_NoNetMarkColor ); - - if( m_layerMask[B_Cu] ) // Draw / - GRLine( nullptr, aDC, holepos.x + dx0, holepos.y - dx0, - holepos.x - dx0, holepos.y + dx0, 0, aDrawInfo.m_NoNetMarkColor ); - } - - // 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 - wxString shortname; - int shortname_len = 0; - - if( aDrawInfo.m_Display_netname ) - { - shortname = UnescapeString( GetShortNetname() ); - shortname_len = shortname.Len(); - } - - if( GetShape() == PAD_SHAPE_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 - */ - constexpr int MIN_CHAR_COUNT = 3; - - unsigned int tsize; - - if( aDrawInfo.m_Display_padnum ) - { - int numpad_len = std::max( (int) m_name.Length(), MIN_CHAR_COUNT ); - tsize = std::min( (int) 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; - GRHaloText( aDC, tpos, aDrawInfo.m_Color, BLACK, WHITE, m_name, 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; - GRHaloText( aDC, tpos, aDrawInfo.m_Color, BLACK, WHITE, shortname, t_angle, - wxSize( tsize, tsize ), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, - tsize / 7, false, false ); - } -} - - -/** - * Function BuildSegmentFromOvalShape - * Has meaning only for OVAL (and ROUND) pads. - * Build an equivalent segment having the same shape as the OVAL shape, - * aSegStart and aSegEnd are the ending points of the equivalent segment of the shape - * aRotation is the asked rotation of the segment (usually m_Orient) - */ -int D_PAD::BuildSegmentFromOvalShape( wxPoint& aSegStart, wxPoint& aSegEnd, double aRotation, - const wxSize& aMargin ) const -{ - int width; - - if( m_Size.y < m_Size.x ) // Build an horizontal equiv segment - { - int delta = ( m_Size.x - m_Size.y ) / 2; - aSegStart.x = -delta - aMargin.x; - aSegStart.y = 0; - aSegEnd.x = delta + aMargin.x; - aSegEnd.y = 0; - width = m_Size.y + ( aMargin.y * 2 ); - } - else // Vertical oval: build a vertical equiv segment - { - int delta = ( m_Size.y -m_Size.x ) / 2; - aSegStart.x = 0; - aSegStart.y = -delta - aMargin.y; - aSegEnd.x = 0; - aSegEnd.y = delta + aMargin.y; - width = m_Size.x + ( aMargin.x * 2 ); - } - - if( aRotation ) - { - RotatePoint( &aSegStart, aRotation); - RotatePoint( &aSegEnd, aRotation); - } - - return width; -} - - -void D_PAD::BuildPadPolygon( wxPoint aCoord[4], wxSize aInflateValue, - double aRotation ) const -{ - wxSize delta; - wxSize halfsize; - - halfsize.x = m_Size.x >> 1; - halfsize.y = m_Size.y >> 1; - - switch( GetShape() ) - { - case PAD_SHAPE_RECT: - // For rectangular shapes, inflate is easy - halfsize += aInflateValue; - - // Verify if do not deflate more than than size - // Only possible for inflate negative values. - if( halfsize.x < 0 ) - halfsize.x = 0; - - if( halfsize.y < 0 ) - halfsize.y = 0; - break; - - case PAD_SHAPE_TRAPEZOID: - // Trapezoidal pad: verify delta values - delta.x = ( m_DeltaSize.x >> 1 ); - delta.y = ( m_DeltaSize.y >> 1 ); - - // be sure delta values are not to large - if( (delta.x < 0) && (delta.x <= -halfsize.y) ) - delta.x = -halfsize.y + 1; - - if( (delta.x > 0) && (delta.x >= halfsize.y) ) - delta.x = halfsize.y - 1; - - if( (delta.y < 0) && (delta.y <= -halfsize.x) ) - delta.y = -halfsize.x + 1; - - if( (delta.y > 0) && (delta.y >= halfsize.x) ) - delta.y = halfsize.x - 1; - break; - - default: // is used only for rect and trap. pads - return; - } - - // Build the basic rectangular or trapezoid shape - // delta is null for rectangular shapes - aCoord[0].x = -halfsize.x - delta.y; // lower left - aCoord[0].y = +halfsize.y + delta.x; - - aCoord[1].x = -halfsize.x + delta.y; // upper left - aCoord[1].y = -halfsize.y - delta.x; - - aCoord[2].x = +halfsize.x - delta.y; // upper right - aCoord[2].y = -halfsize.y + delta.x; - - aCoord[3].x = +halfsize.x + delta.y; // lower right - aCoord[3].y = +halfsize.y - delta.x; - - // Offsetting the trapezoid shape id needed - // It is assumed delta.x or/and delta.y == 0 - if( GetShape() == PAD_SHAPE_TRAPEZOID && (aInflateValue.x != 0 || aInflateValue.y != 0) ) - { - double angle; - wxSize corr; - - if( delta.y ) // lower and upper segment is horizontal - { - // Calculate angle of left (or right) segment with vertical axis - angle = atan2( (double) m_DeltaSize.y, (double) m_Size.y ); - - // left and right sides are moved by aInflateValue.x in their perpendicular direction - // We must calculate the corresponding displacement on the horizontal axis - // that is delta.x +- corr.x depending on the corner - corr.x = KiROUND( tan( angle ) * aInflateValue.x ); - delta.x = KiROUND( aInflateValue.x / cos( angle ) ); - - // Horizontal sides are moved up and down by aInflateValue.y - delta.y = aInflateValue.y; - - // corr.y = 0 by the constructor - } - else if( delta.x ) // left and right segment is vertical - { - // Calculate angle of lower (or upper) segment with horizontal axis - angle = atan2( (double) m_DeltaSize.x, (double) m_Size.x ); - - // lower and upper sides are moved by aInflateValue.x in their perpendicular direction - // We must calculate the corresponding displacement on the vertical axis - // that is delta.y +- corr.y depending on the corner - corr.y = KiROUND( tan( angle ) * aInflateValue.y ); - delta.y = KiROUND( aInflateValue.y / cos( angle ) ); - - // Vertical sides are moved left and right by aInflateValue.x - delta.x = aInflateValue.x; - - // corr.x = 0 by the constructor - } - else // the trapezoid is a rectangle - { - delta = aInflateValue; // this pad is rectangular (delta null). - } - - aCoord[0].x += -delta.x - corr.x; // lower left - aCoord[0].y += delta.y + corr.y; - - aCoord[1].x += -delta.x + corr.x; // upper left - aCoord[1].y += -delta.y - corr.y; - - aCoord[2].x += delta.x - corr.x; // upper right - aCoord[2].y += -delta.y + corr.y; - - aCoord[3].x += delta.x + corr.x; // lower right - aCoord[3].y += delta.y - corr.y; - - /* test coordinates and clamp them if the offset correction is too large: - * Note: if a coordinate is bad, the other "symmetric" coordinate is bad - * So when a bad coordinate is found, the 2 symmetric coordinates - * are set to the minimun value (0) - */ - - if( aCoord[0].x > 0 ) // lower left x coordinate must be <= 0 - aCoord[0].x = aCoord[3].x = 0; - - if( aCoord[1].x > 0 ) // upper left x coordinate must be <= 0 - aCoord[1].x = aCoord[2].x = 0; - - if( aCoord[0].y < 0 ) // lower left y coordinate must be >= 0 - aCoord[0].y = aCoord[1].y = 0; - - if( aCoord[3].y < 0 ) // lower right y coordinate must be >= 0 - aCoord[3].y = aCoord[2].y = 0; - } - - if( aRotation ) - { - for( int ii = 0; ii < 4; ii++ ) - RotatePoint( &aCoord[ii], aRotation ); - } -}