diff --git a/pcbnew/pcb_io/altium/altium_parser_pcb.cpp b/pcbnew/pcb_io/altium/altium_parser_pcb.cpp index c644c82f29..8f7630b419 100644 --- a/pcbnew/pcb_io/altium/altium_parser_pcb.cpp +++ b/pcbnew/pcb_io/altium/altium_parser_pcb.cpp @@ -1040,14 +1040,13 @@ ATEXT6::ATEXT6( ALTIUM_BINARY_PARSER& aReader, std::map& aSt widestring_index = aReader.Read(); aReader.Skip( 4 ); - // An inverted rect in Altium is like a text box with the text inverted. The box has a defined - // width and height, justification and offet (indent). This is not currently supported in KiCad. + // An inverted rect in Altium is like a text box with the text inverted. isInvertedRect = aReader.Read() != 0; - inverted_rect_width = aReader.ReadKicadUnit(); - inverted_rect_height = aReader.ReadKicadUnit(); - inverted_rect_justification = static_cast( aReader.Read() ); - inverted_rect_offset = aReader.ReadKicadUnit(); + textbox_rect_width = aReader.ReadKicadUnit(); + textbox_rect_height = aReader.ReadKicadUnit(); + textbox_rect_justification = static_cast( aReader.Read() ); + textbox_rect_offset = aReader.ReadKicadUnit(); aReader.SkipSubrecord(); // Subrecord 2 - Legacy 8bit string, max 255 chars, unknown codepage diff --git a/pcbnew/pcb_io/altium/altium_parser_pcb.h b/pcbnew/pcb_io/altium/altium_parser_pcb.h index 1066fc45a3..e5dcfd4929 100644 --- a/pcbnew/pcb_io/altium/altium_parser_pcb.h +++ b/pcbnew/pcb_io/altium/altium_parser_pcb.h @@ -741,13 +741,13 @@ struct ATEXT6 bool isInverted; bool isInvertedRect; uint32_t inverted_borderwidth; - uint32_t inverted_rect_width; - uint32_t inverted_rect_height; - uint32_t inverted_rect_offset; + uint32_t textbox_rect_width; + uint32_t textbox_rect_height; + uint32_t textbox_rect_offset; // Justification only applies when there is a text box size specified // Then, the text is justified within the box - ALTIUM_TEXT_POSITION inverted_rect_justification; + ALTIUM_TEXT_POSITION textbox_rect_justification; uint32_t widestring_index; diff --git a/pcbnew/pcb_io/altium/altium_pcb.cpp b/pcbnew/pcb_io/altium/altium_pcb.cpp index b33f6675a3..7ad1de0e80 100644 --- a/pcbnew/pcb_io/altium/altium_pcb.cpp +++ b/pcbnew/pcb_io/altium/altium_pcb.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -4072,43 +4073,115 @@ void ALTIUM_PCB::ConvertTexts6ToFootprintItem( FOOTPRINT* aFootprint, const ATEX void ALTIUM_PCB::ConvertTexts6ToBoardItemOnLayer( const ATEXT6& aElem, PCB_LAYER_ID aLayer ) { + std::unique_ptr pcbTextbox = std::make_unique( m_board ); std::unique_ptr pcbText = std::make_unique( m_board ); + bool isTextbox = ( aElem.textbox_rect_height != 0 ); static const std::map variableMap = { { "LAYER_NAME", "LAYER" }, { "PRINT_DATE", "CURRENT_DATE"}, }; - wxString kicadText = AltiumPcbSpecialStringsToKiCadStrings( aElem.text, variableMap ); + wxString kicadText = AltiumPcbSpecialStringsToKiCadStrings( aElem.text, variableMap ); + BOARD_ITEM* item = pcbText.get(); + EDA_TEXT* text = pcbText.get(); - pcbText->SetText(kicadText); - pcbText->SetLayer( aLayer ); - pcbText->SetPosition( aElem.position ); - pcbText->SetIsKnockout( aElem.isInverted ); + if( isTextbox ) + { + // Altium textboxes do not have borders + pcbTextbox->SetBorderEnabled( false ); - ConvertTexts6ToEdaTextSettings( aElem, *pcbText ); + item = pcbTextbox.get(); + text = pcbTextbox.get(); + pcbTextbox->SetPosition( aElem.position ); + pcbTextbox->SetRectangleHeight( -aElem.textbox_rect_height ); + pcbTextbox->SetRectangleWidth( aElem.textbox_rect_width ); - m_board->Add( pcbText.release(), ADD_MODE::APPEND ); + switch( aElem.textbox_rect_justification ) + { + case ALTIUM_TEXT_POSITION::LEFT_TOP: + case ALTIUM_TEXT_POSITION::LEFT_CENTER: + case ALTIUM_TEXT_POSITION::LEFT_BOTTOM: + pcbTextbox->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); + pcbTextbox->SetVertJustify( GR_TEXT_V_ALIGN_TOP ); + break; + case ALTIUM_TEXT_POSITION::CENTER_TOP: + case ALTIUM_TEXT_POSITION::CENTER_CENTER: + case ALTIUM_TEXT_POSITION::CENTER_BOTTOM: + pcbTextbox->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER ); + pcbTextbox->SetVertJustify( GR_TEXT_V_ALIGN_TOP ); + break; + case ALTIUM_TEXT_POSITION::RIGHT_TOP: + case ALTIUM_TEXT_POSITION::RIGHT_CENTER: + case ALTIUM_TEXT_POSITION::RIGHT_BOTTOM: + pcbTextbox->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); + pcbTextbox->SetVertJustify( GR_TEXT_V_ALIGN_TOP ); + break; + default: + if( m_reporter ) + { + wxString msg; + msg.Printf( _( "Unknown textbox justification %d, text %s" ), + aElem.textbox_rect_justification, aElem.text ); + m_reporter->Report( msg, RPT_SEVERITY_DEBUG ); + } + + pcbTextbox->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); + pcbTextbox->SetVertJustify( GR_TEXT_V_ALIGN_TOP ); + break; + } + + } + else + { + pcbText->SetPosition( aElem.position ); + pcbText->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); + pcbText->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM ); + } + + text->SetText(kicadText); + item->SetLayer( aLayer ); + item->SetIsKnockout( aElem.isInverted ); + + ConvertTexts6ToEdaTextSettings( aElem, *text ); + + if( isTextbox ) + m_board->Add( pcbTextbox.release(), ADD_MODE::APPEND ); + else + m_board->Add( pcbText.release(), ADD_MODE::APPEND ); } void ALTIUM_PCB::ConvertTexts6ToFootprintItemOnLayer( FOOTPRINT* aFootprint, const ATEXT6& aElem, PCB_LAYER_ID aLayer ) { - PCB_TEXT* fpText; + std::unique_ptr fpTextbox = std::make_unique( aFootprint ); + std::unique_ptr fpText = std::make_unique( aFootprint ); + + BOARD_ITEM* item = fpText.get(); + EDA_TEXT* text = fpText.get(); + PCB_FIELD* field = nullptr; + + bool isTextbox = ( aElem.textbox_rect_height != 0 ); + bool toAdd = false; if( aElem.isDesignator ) { - fpText = &aFootprint->Reference(); // TODO: handle multiple layers + item = &aFootprint->Reference(); // TODO: handle multiple layers + text = &aFootprint->Reference(); + field = &aFootprint->Reference(); } else if( aElem.isComment ) { - fpText = &aFootprint->Value(); // TODO: handle multiple layers + item = &aFootprint->Value(); // TODO: handle multiple layers + text = &aFootprint->Value(); + field = &aFootprint->Value(); } else { - fpText = new PCB_TEXT( aFootprint ); - aFootprint->Add( fpText, ADD_MODE::APPEND ); + item = fpText.get(); + text = fpText.get(); + toAdd = true; } static const std::map variableMap = { @@ -4121,19 +4194,78 @@ void ALTIUM_PCB::ConvertTexts6ToFootprintItemOnLayer( FOOTPRINT* aFootprint, con wxString kicadText = AltiumPcbSpecialStringsToKiCadStrings( aElem.text, variableMap ); - fpText->SetText(kicadText); - fpText->SetKeepUpright( false ); - fpText->SetLayer( aLayer ); - fpText->SetPosition( aElem.position ); - fpText->SetIsKnockout( aElem.isInverted ); + text->SetText(kicadText); + text->SetKeepUpright( false ); + item->SetLayer( aLayer ); + item->SetIsKnockout( aElem.isInverted ); - ConvertTexts6ToEdaTextSettings( aElem, *fpText ); + if( isTextbox ) + { + item = fpTextbox.get(); + text = fpTextbox.get(); + fpTextbox->SetPosition( aElem.position ); + fpTextbox->SetRectangleHeight( aElem.textbox_rect_height ); + fpTextbox->SetRectangleWidth( aElem.textbox_rect_width ); + + // KiCad only does top alignment for textboxes atm + switch( aElem.textbox_rect_justification ) + { + case ALTIUM_TEXT_POSITION::LEFT_TOP: + case ALTIUM_TEXT_POSITION::LEFT_CENTER: + case ALTIUM_TEXT_POSITION::LEFT_BOTTOM: + fpTextbox->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); + fpTextbox->SetVertJustify( GR_TEXT_V_ALIGN_TOP ); + break; + case ALTIUM_TEXT_POSITION::CENTER_TOP: + case ALTIUM_TEXT_POSITION::CENTER_CENTER: + case ALTIUM_TEXT_POSITION::CENTER_BOTTOM: + fpTextbox->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER ); + fpTextbox->SetVertJustify( GR_TEXT_V_ALIGN_TOP ); + break; + case ALTIUM_TEXT_POSITION::RIGHT_TOP: + case ALTIUM_TEXT_POSITION::RIGHT_CENTER: + case ALTIUM_TEXT_POSITION::RIGHT_BOTTOM: + fpTextbox->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); + fpTextbox->SetVertJustify( GR_TEXT_V_ALIGN_TOP ); + break; + default: + if( m_reporter ) + { + wxString msg; + msg.Printf( _( "Unknown textbox justification %d, text %s" ), + aElem.textbox_rect_justification, aElem.text ); + m_reporter->Report( msg, RPT_SEVERITY_DEBUG ); + } + + fpTextbox->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); + fpTextbox->SetVertJustify( GR_TEXT_V_ALIGN_TOP ); + break; + } + + } + else + { + field->SetPosition( aElem.position ); + } + + ConvertTexts6ToEdaTextSettings( aElem, *text ); + + if( toAdd ) + { + if( isTextbox ) + aFootprint->Add( fpTextbox.release(), ADD_MODE::APPEND ); + else + aFootprint->Add( fpText.release(), ADD_MODE::APPEND ); + } } void ALTIUM_PCB::ConvertTexts6ToEdaTextSettings( const ATEXT6& aElem, EDA_TEXT& aEdaText ) { - aEdaText.SetTextSize( VECTOR2I( aElem.height, aElem.height ) ); // TODO: parse text width + // Altium counts the width of the text from the centerline of each stroke while KiCad measures + // it to the outside of the stroke. TODO: need to adjust this based on the stroke font. Altium Default is + // definitely wider than the sans serif font. + aEdaText.SetTextSize( VECTOR2I( aElem.height, aElem.height + aElem.strokewidth ) ); if( aElem.fonttype == ALTIUM_TEXT_TYPE::TRUETYPE ) { @@ -4155,10 +4287,6 @@ void ALTIUM_PCB::ConvertTexts6ToEdaTextSettings( const ATEXT6& aElem, EDA_TEXT& aEdaText.SetItalic( aElem.isItalic ); aEdaText.SetMirrored( aElem.isMirrored ); aEdaText.SetTextAngle( EDA_ANGLE( aElem.rotation, DEGREES_T ) ); - - aEdaText.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); - aEdaText.SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM ); - }