From b11e030f8fe40ac7b39a6ddcabfc5b188333e318 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Sun, 16 Jun 2024 13:07:39 -0700 Subject: [PATCH] Cleanup Altium text import Handle inverted text Correct location for flags Add mechanics to detect inverted_rect (like text boxes) --- pcbnew/pcb_io/altium/altium_parser_pcb.cpp | 46 +++++++++++++++------- pcbnew/pcb_io/altium/altium_parser_pcb.h | 21 +++++++++- pcbnew/pcb_io/altium/altium_pcb.cpp | 7 ++-- 3 files changed, 54 insertions(+), 20 deletions(-) diff --git a/pcbnew/pcb_io/altium/altium_parser_pcb.cpp b/pcbnew/pcb_io/altium/altium_parser_pcb.cpp index 1743549947..c644c82f29 100644 --- a/pcbnew/pcb_io/altium/altium_parser_pcb.cpp +++ b/pcbnew/pcb_io/altium/altium_parser_pcb.cpp @@ -1010,13 +1010,23 @@ ATEXT6::ATEXT6( ALTIUM_BINARY_PARSER& aReader, std::map& aSt aReader.Skip( 4 ); position = aReader.ReadVector2IPos(); height = aReader.ReadKicadUnit(); - aReader.Skip( 2 ); + strokefonttype = static_cast( aReader.Read() ); + // TODO: The Serif font type doesn't match well with KiCad, we should replace it with a better match + rotation = aReader.Read(); isMirrored = aReader.Read() != 0; strokewidth = aReader.ReadKicadUnit(); + + if( subrecord1 < 123 ) + { + aReader.SkipSubrecord(); + return; + } + isComment = aReader.Read() != 0; isDesignator = aReader.Read() != 0; - aReader.Skip( 2 ); + aReader.Skip( 1 ); + fonttype = static_cast( aReader.Read() ); isBold = aReader.Read() != 0; isItalic = aReader.Read() != 0; @@ -1024,27 +1034,26 @@ ATEXT6::ATEXT6( ALTIUM_BINARY_PARSER& aReader, std::map& aSt aReader.ReadBytes( fontData, sizeof( fontData ) ); fontname = wxString( fontData, wxMBConvUTF16LE(), sizeof( fontData ) ).BeforeFirst( '\0' ); - isInverted = aReader.Read() != 0; + char tmpbyte = aReader.Read(); + isInverted = !!tmpbyte; + inverted_borderwidth = aReader.ReadKicadUnit(); + widestring_index = aReader.Read(); aReader.Skip( 4 ); - uint32_t stringIndex = aReader.Read(); - aReader.Skip( 13 ); - textposition = static_cast( aReader.Read() ); - /** - * In Altium 14 (subrecord1 == 230) only left bottom is valid? I think there is a bit missing. - * https://gitlab.com/kicad/code/kicad/-/merge_requests/60#note_274913397 - */ - if( subrecord1 <= 230 ) - textposition = ALTIUM_TEXT_POSITION::LEFT_BOTTOM; - aReader.Skip( 27 ); - fonttype = static_cast( aReader.Read() ); + // 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. + 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(); aReader.SkipSubrecord(); // Subrecord 2 - Legacy 8bit string, max 255 chars, unknown codepage aReader.ReadAndSetSubrecordLength(); - auto entry = aStringTable.find( stringIndex ); + auto entry = aStringTable.find( widestring_index ); if( entry != aStringTable.end() ) text = entry->second; @@ -1056,6 +1065,13 @@ ATEXT6::ATEXT6( ALTIUM_BINARY_PARSER& aReader, std::map& aSt aReader.SkipSubrecord(); + // Altium only supports inverting truetype fonts + if( fonttype != ALTIUM_TEXT_TYPE::TRUETYPE ) + { + isInverted = false; + isInvertedRect = false; + } + if( aReader.HasParsingError() ) THROW_IO_ERROR( wxT( "Texts6 stream was not parsed correctly" ) ); } diff --git a/pcbnew/pcb_io/altium/altium_parser_pcb.h b/pcbnew/pcb_io/altium/altium_parser_pcb.h index 3258885222..1066fc45a3 100644 --- a/pcbnew/pcb_io/altium/altium_parser_pcb.h +++ b/pcbnew/pcb_io/altium/altium_parser_pcb.h @@ -718,6 +718,14 @@ struct ATRACK6 struct ATEXT6 { + enum class STROKE_FONT_TYPE + { + DEFAULT = 1, + SANSSERIF = 2, + SERIF = 3 + }; + + ALTIUM_LAYER layer; uint16_t component; @@ -725,12 +733,23 @@ struct ATEXT6 uint32_t height; double rotation; uint32_t strokewidth; - ALTIUM_TEXT_POSITION textposition; + STROKE_FONT_TYPE strokefonttype; bool isBold; bool isItalic; bool isMirrored; bool isInverted; + bool isInvertedRect; + uint32_t inverted_borderwidth; + uint32_t inverted_rect_width; + uint32_t inverted_rect_height; + uint32_t inverted_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; + + uint32_t widestring_index; bool isComment; bool isDesignator; diff --git a/pcbnew/pcb_io/altium/altium_pcb.cpp b/pcbnew/pcb_io/altium/altium_pcb.cpp index fe0b29a47f..b33f6675a3 100644 --- a/pcbnew/pcb_io/altium/altium_pcb.cpp +++ b/pcbnew/pcb_io/altium/altium_pcb.cpp @@ -4084,7 +4084,7 @@ void ALTIUM_PCB::ConvertTexts6ToBoardItemOnLayer( const ATEXT6& aElem, PCB_LAYER pcbText->SetText(kicadText); pcbText->SetLayer( aLayer ); pcbText->SetPosition( aElem.position ); - pcbText->SetTextAngle( EDA_ANGLE( aElem.rotation, DEGREES_T ) ); + pcbText->SetIsKnockout( aElem.isInverted ); ConvertTexts6ToEdaTextSettings( aElem, *pcbText ); @@ -4125,7 +4125,7 @@ void ALTIUM_PCB::ConvertTexts6ToFootprintItemOnLayer( FOOTPRINT* aFootprint, con fpText->SetKeepUpright( false ); fpText->SetLayer( aLayer ); fpText->SetPosition( aElem.position ); - fpText->SetTextAngle( EDA_ANGLE( aElem.rotation, DEGREES_T ) ); + fpText->SetIsKnockout( aElem.isInverted ); ConvertTexts6ToEdaTextSettings( aElem, *fpText ); } @@ -4154,12 +4154,11 @@ void ALTIUM_PCB::ConvertTexts6ToEdaTextSettings( const ATEXT6& aElem, EDA_TEXT& aEdaText.SetBoldFlag( aElem.isBold ); aEdaText.SetItalic( aElem.isItalic ); aEdaText.SetMirrored( aElem.isMirrored ); + aEdaText.SetTextAngle( EDA_ANGLE( aElem.rotation, DEGREES_T ) ); - // Altium position always specifies the bottom left corner aEdaText.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); aEdaText.SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM ); - // TODO: correct the position and set proper justification }