Cleanup GRText APIs, 3D Viewer <-> board APIs, and Plotter APIs.

Also fixes a bug where outline fonts weren't being handled for footprint
text in 3D Viewer, and a copy/paste error in stroke font handling for
both PCB and footprint text in 3D Viewer.

Fixes https://gitlab.com/kicad/code/kicad/issues/10319
This commit is contained in:
Jeff Young 2022-01-10 14:03:53 +00:00
parent 2563518f3a
commit 236feeb592
9 changed files with 165 additions and 298 deletions

View File

@ -465,32 +465,25 @@ private:
void destroyLayers(); void destroyLayers();
// Helper functions to create the board // Helper functions to create the board
void createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer, void createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer );
int aClearanceValue );
void createPadWithClearance( const PAD *aPad, CONTAINER_2D_BASE* aDstContainer, void createPadWithMargin( const PAD *aPad, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayer, const VECTOR2I& aClearanceValue ) const; PCB_LAYER_ID aLayer, const VECTOR2I& aMargin ) const;
OBJECT_2D* createPadWithDrill( const PAD* aPad, int aInflateValue ); OBJECT_2D* createPadWithDrill( const PAD* aPad, int aInflateValue );
void addPadsWithClearance( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer, void addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId, int aInflateValue, PCB_LAYER_ID aLayerId, bool aSkipNPTHPadsWihNoCopper, bool aSkipPlatedPads,
bool aSkipNPTHPadsWihNoCopper, bool aSkipPlatedPads, bool aSkipNonPlatedPads );
bool aSkipNonPlatedPads );
void addFootprintShapesWithClearance( const FOOTPRINT* aFootprint, void addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
CONTAINER_2D_BASE* aDstContainer, PCB_LAYER_ID aLayerId );
PCB_LAYER_ID aLayerId, int aInflateValue );
void addShapeWithClearance( const PCB_TEXT* aText, CONTAINER_2D_BASE* aDstContainer, void addShape( const PCB_TEXT* aText, CONTAINER_2D_BASE* aDstContainer );
PCB_LAYER_ID aLayerId, int aClearanceValue );
void addShapeWithClearance( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aDstContainer, void addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aDstContainer );
PCB_LAYER_ID aLayerId, int aClearanceValue );
void addShapeWithClearance( const PCB_DIMENSION_BASE* aDimension, void addShape( const PCB_DIMENSION_BASE* aDimension, CONTAINER_2D_BASE* aDstContainer );
CONTAINER_2D_BASE* aDstContainer, PCB_LAYER_ID aLayerId,
int aClearanceValue );
void addSolidAreasShapes( const ZONE* aZoneContainer, CONTAINER_2D_BASE* aDstContainer, void addSolidAreasShapes( const ZONE* aZoneContainer, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId ); PCB_LAYER_ID aLayerId );

View File

@ -49,50 +49,31 @@
#include <geometry/shape_circle.h> #include <geometry/shape_circle.h>
#include <geometry/shape_rect.h> #include <geometry/shape_rect.h>
#include <geometry/shape_simple.h> #include <geometry/shape_simple.h>
#include <gr_text.h>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <wx/log.h> #include <wx/log.h>
#include <macros.h> #include <macros.h>
#include <callback_gal.h>
void BOARD_ADAPTER::addShape( const PCB_TEXT* aText, CONTAINER_2D_BASE* aDstContainer )
// Based on
// void PCB_TEXT::TransformTextShapeWithClearanceToPolygon
// board_items_to_polygon_shape_transform.cpp
void BOARD_ADAPTER::addShapeWithClearance( const PCB_TEXT* aText, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId, int aClearanceValue )
{ {
VECTOR2I size = aText->GetTextSize(); KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
KIFONT::FONT* font = aText->GetDrawFont();
int penWidth = aText->GetEffectiveTextPenWidth() * m_biuTo3Dunits;
if( aText->IsMirrored() ) CALLBACK_GAL callback_gal( empty_opts,
size.x = -size.x; // Stroke callback
// Use the actual text width to generate segments. The segment position depend on
// text thickness and justification
int penWidth = aText->GetEffectiveTextPenWidth();
int adjustedWidth = penWidth + ( 2 * aClearanceValue );
GRText( aText->GetTextPos(), aText->GetShownText(), aText->GetTextAngle(), size,
aText->GetHorizJustify(), aText->GetVertJustify(), penWidth, aText->IsItalic(),
aText->IsBold(), aText->GetDrawFont(),
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 ) [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{ {
const SFVEC2F start3DU( aPt1.x * m_biuTo3Dunits, -aPt1.y * m_biuTo3Dunits ); const SFVEC2F a3DU( aPt1.x * m_biuTo3Dunits, -aPt1.y * m_biuTo3Dunits );
const SFVEC2F end3DU ( aPt1.x * m_biuTo3Dunits, -aPt2.y * m_biuTo3Dunits ); const SFVEC2F b3DU( aPt2.x * m_biuTo3Dunits, -aPt2.y * m_biuTo3Dunits );
if( Is_segment_a_circle( start3DU, end3DU ) ) if( Is_segment_a_circle( a3DU, b3DU ) )
{ aDstContainer->Add( new FILLED_CIRCLE_2D( a3DU, penWidth / 2, *aText ) );
aDstContainer->Add( new FILLED_CIRCLE_2D( start3DU,
adjustedWidth * m_biuTo3Dunits / 2,
*aText ) );
}
else else
{ aDstContainer->Add( new ROUND_SEGMENT_2D( a3DU, b3DU, penWidth, *aText ) );
aDstContainer->Add( new ROUND_SEGMENT_2D( start3DU, end3DU,
adjustedWidth * m_biuTo3Dunits,
*aText ) );
}
}, },
// Triangulation callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 ) [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
{ {
const SFVEC2F a3DU( aPt1.x * m_biuTo3Dunits, -aPt1.y * m_biuTo3Dunits ); const SFVEC2F a3DU( aPt1.x * m_biuTo3Dunits, -aPt1.y * m_biuTo3Dunits );
@ -101,16 +82,17 @@ void BOARD_ADAPTER::addShapeWithClearance( const PCB_TEXT* aText, CONTAINER_2D_B
aDstContainer->Add( new TRIANGLE_2D( a3DU, b3DU, c3DU, *aText ) ); aDstContainer->Add( new TRIANGLE_2D( a3DU, b3DU, c3DU, *aText ) );
} ); } );
font->Draw( &callback_gal, aText->GetShownText(), aText->GetTextPos(), aText->GetAttributes() );
} }
void BOARD_ADAPTER::addShapeWithClearance( const PCB_DIMENSION_BASE* aDimension, void BOARD_ADAPTER::addShape( const PCB_DIMENSION_BASE* aDimension,
CONTAINER_2D_BASE* aDstContainer, CONTAINER_2D_BASE* aDstContainer )
PCB_LAYER_ID aLayerId, int aClearanceValue )
{ {
addShapeWithClearance( &aDimension->Text(), aDstContainer, aLayerId, aClearanceValue ); addShape( &aDimension->Text(), aDstContainer );
const int linewidth = aDimension->GetLineThickness() + ( 2 * aClearanceValue ); const int linewidth = aDimension->GetLineThickness();
for( const std::shared_ptr<SHAPE>& shape : aDimension->GetShapes() ) for( const std::shared_ptr<SHAPE>& shape : aDimension->GetShapes() )
{ {
@ -118,11 +100,9 @@ void BOARD_ADAPTER::addShapeWithClearance( const PCB_DIMENSION_BASE* aDimension,
{ {
case SH_SEGMENT: case SH_SEGMENT:
{ {
const SEG& seg = static_cast<const SHAPE_SEGMENT*>( shape.get() )->GetSeg(); const SEG& seg = static_cast<const SHAPE_SEGMENT*>( shape.get() )->GetSeg();
const SFVEC2F start3DU( seg.A.x * m_biuTo3Dunits, -seg.A.y * m_biuTo3Dunits ); const SFVEC2F start3DU( seg.A.x * m_biuTo3Dunits, -seg.A.y * m_biuTo3Dunits );
const SFVEC2F end3DU ( seg.B.x * m_biuTo3Dunits, -seg.B.y * m_biuTo3Dunits );
const SFVEC2F end3DU( seg.B.x * m_biuTo3Dunits, -seg.B.y * m_biuTo3Dunits );
aDstContainer->Add( new ROUND_SEGMENT_2D( start3DU, end3DU, linewidth * m_biuTo3Dunits, aDstContainer->Add( new ROUND_SEGMENT_2D( start3DU, end3DU, linewidth * m_biuTo3Dunits,
*aDimension ) ); *aDimension ) );
@ -132,13 +112,13 @@ void BOARD_ADAPTER::addShapeWithClearance( const PCB_DIMENSION_BASE* aDimension,
case SH_CIRCLE: case SH_CIRCLE:
{ {
int radius = static_cast<const SHAPE_CIRCLE*>( shape.get() )->GetRadius(); int radius = static_cast<const SHAPE_CIRCLE*>( shape.get() )->GetRadius();
int deltar = aDimension->GetLineThickness(); int delta = aDimension->GetLineThickness() / 2;
SFVEC2F center( shape->Centre().x * m_biuTo3Dunits, SFVEC2F center( shape->Centre().x * m_biuTo3Dunits,
shape->Centre().y * m_biuTo3Dunits ); shape->Centre().y * m_biuTo3Dunits );
aDstContainer->Add( new RING_2D( center, ( radius - deltar ) * m_biuTo3Dunits, aDstContainer->Add( new RING_2D( center, ( radius - delta ) * m_biuTo3Dunits,
( radius + deltar ) * m_biuTo3Dunits, *aDimension ) ); ( radius + delta ) * m_biuTo3Dunits, *aDimension ) );
break; break;
} }
@ -150,14 +130,41 @@ void BOARD_ADAPTER::addShapeWithClearance( const PCB_DIMENSION_BASE* aDimension,
} }
// Based on void BOARD_ADAPTER::addFootprintShapes( const FOOTPRINT* aFootprint,
// void FOOTPRINT::TransformFPShapesWithClearanceToPolygonSet CONTAINER_2D_BASE* aDstContainer, PCB_LAYER_ID aLayerId )
// board_items_to_polygon_shape_transform.cpp#L204
void BOARD_ADAPTER::addFootprintShapesWithClearance( const FOOTPRINT* aFootprint,
CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId, int aInflateValue )
{ {
std::vector<FP_TEXT*> texts; // List of FP_TEXT to convert KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
std::vector<FP_TEXT*> textItems;
FP_TEXT* textItem = nullptr;
float penWidth = 0;
CALLBACK_GAL callback_gal( empty_opts,
// Stroke callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{
const SFVEC2F a3DU( aPt1.x * m_biuTo3Dunits, -aPt1.y * m_biuTo3Dunits );
const SFVEC2F b3DU( aPt2.x * m_biuTo3Dunits, -aPt2.y * m_biuTo3Dunits );
if( Is_segment_a_circle( a3DU, b3DU ) )
aDstContainer->Add( new FILLED_CIRCLE_2D( a3DU, penWidth / 2, *textItem ) );
else
aDstContainer->Add( new ROUND_SEGMENT_2D( a3DU, b3DU, penWidth, *textItem ) );
},
// Triangulation callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
{
const SFVEC2F a3DU( aPt1.x * m_biuTo3Dunits, -aPt1.y * m_biuTo3Dunits );
const SFVEC2F b3DU( aPt2.x * m_biuTo3Dunits, -aPt2.y * m_biuTo3Dunits );
const SFVEC2F c3DU( aPt3.x * m_biuTo3Dunits, -aPt3.y * m_biuTo3Dunits );
aDstContainer->Add( new TRIANGLE_2D( a3DU, b3DU, c3DU, *textItem ) );
} );
if( aFootprint->Reference().GetLayer() == aLayerId && aFootprint->Reference().IsVisible() )
textItems.push_back( &aFootprint->Reference() );
if( aFootprint->Value().GetLayer() == aLayerId && aFootprint->Value().IsVisible() )
textItems.push_back( &aFootprint->Value() );
for( BOARD_ITEM* item : aFootprint->GraphicalItems() ) for( BOARD_ITEM* item : aFootprint->GraphicalItems() )
{ {
@ -168,7 +175,7 @@ void BOARD_ADAPTER::addFootprintShapesWithClearance( const FOOTPRINT* aFootprint
FP_TEXT* text = static_cast<FP_TEXT*>( item ); FP_TEXT* text = static_cast<FP_TEXT*>( item );
if( text->GetLayer() == aLayerId && text->IsVisible() ) if( text->GetLayer() == aLayerId && text->IsVisible() )
texts.push_back( text ); textItems.push_back( text );
break; break;
} }
@ -182,7 +189,7 @@ void BOARD_ADAPTER::addFootprintShapesWithClearance( const FOOTPRINT* aFootprint
PCB_DIMENSION_BASE* dimension = static_cast<PCB_DIMENSION_BASE*>( item ); PCB_DIMENSION_BASE* dimension = static_cast<PCB_DIMENSION_BASE*>( item );
if( dimension->GetLayer() == aLayerId ) if( dimension->GetLayer() == aLayerId )
addShapeWithClearance( dimension, aDstContainer, aLayerId, 0 ); addShape( dimension, aDstContainer );
break; break;
} }
@ -192,7 +199,7 @@ void BOARD_ADAPTER::addFootprintShapesWithClearance( const FOOTPRINT* aFootprint
FP_SHAPE* shape = static_cast<FP_SHAPE*>( item ); FP_SHAPE* shape = static_cast<FP_SHAPE*>( item );
if( shape->GetLayer() == aLayerId ) if( shape->GetLayer() == aLayerId )
addShapeWithClearance( (const PCB_SHAPE*) shape, aDstContainer, aLayerId, 0 ); addShape( static_cast<const PCB_SHAPE*>( shape ), aDstContainer );
break; break;
} }
@ -202,53 +209,20 @@ void BOARD_ADAPTER::addFootprintShapesWithClearance( const FOOTPRINT* aFootprint
} }
} }
// Convert texts for footprints for( FP_TEXT* text : textItems )
if( aFootprint->Reference().GetLayer() == aLayerId && aFootprint->Reference().IsVisible() )
texts.push_back( &aFootprint->Reference() );
if( aFootprint->Value().GetLayer() == aLayerId && aFootprint->Value().IsVisible() )
texts.push_back( &aFootprint->Value() );
for( FP_TEXT* text : texts )
{ {
VECTOR2I size = text->GetTextSize(); textItem = text;
int penWidth = text->GetEffectiveTextPenWidth(); penWidth = textItem->GetEffectiveTextPenWidth() * m_biuTo3Dunits;
int adjustedWidth = penWidth + ( 2 * aInflateValue );
if( text->IsMirrored() ) KIFONT::FONT* font = textItem->GetDrawFont();
size.x = -size.x;
GRText( text->GetTextPos(), text->GetShownText(), text->GetTextAngle(), size, font->Draw( &callback_gal, textItem->GetShownText(), textItem->GetTextPos(),
text->GetHorizJustify(), text->GetVertJustify(), penWidth, text->IsItalic(), textItem->GetAttributes() );
text->IsBold(), text->GetDrawFont(),
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{
const SFVEC2F start3DU( aPt1.x * m_biuTo3Dunits, -aPt1.y * m_biuTo3Dunits );
const SFVEC2F end3DU ( aPt1.x * m_biuTo3Dunits, -aPt2.y * m_biuTo3Dunits );
if( Is_segment_a_circle( start3DU, end3DU ) )
{
aDstContainer->Add( new FILLED_CIRCLE_2D( start3DU,
adjustedWidth * m_biuTo3Dunits / 2,
aFootprint->Value() ) );
}
else
{
aDstContainer->Add( new ROUND_SEGMENT_2D( start3DU, end3DU,
adjustedWidth * m_biuTo3Dunits,
aFootprint->Value() ) );
}
},
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
{
//FONT TODO: add triangle to container
} );
} }
} }
void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer, void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer )
int aClearanceValue )
{ {
SFVEC2F start3DU( aTrack->GetStart().x * m_biuTo3Dunits, SFVEC2F start3DU( aTrack->GetStart().x * m_biuTo3Dunits,
-aTrack->GetStart().y * m_biuTo3Dunits ); // y coord is inverted -aTrack->GetStart().y * m_biuTo3Dunits ); // y coord is inverted
@ -257,7 +231,7 @@ void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDs
{ {
case PCB_VIA_T: case PCB_VIA_T:
{ {
const float radius = ( ( aTrack->GetWidth() / 2 ) + aClearanceValue ) * m_biuTo3Dunits; const float radius = ( aTrack->GetWidth() / 2 ) * m_biuTo3Dunits;
aDstContainer->Add( new FILLED_CIRCLE_2D( start3DU, radius, *aTrack ) ); aDstContainer->Add( new FILLED_CIRCLE_2D( start3DU, radius, *aTrack ) );
break; break;
} }
@ -274,7 +248,9 @@ void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDs
// We need a circle to segment count. However, the arc angle can be small, and the // We need a circle to segment count. However, the arc angle can be small, and the
// radius very big. so we calculate a reasonable value for circlesegcount. // radius very big. so we calculate a reasonable value for circlesegcount.
if( arcsegcount <= 1 ) // The arc will be approximated by a segment if( arcsegcount <= 1 ) // The arc will be approximated by a segment
{
circlesegcount = 1; circlesegcount = 1;
}
else else
{ {
double cnt = arcsegcount * 3600/std::abs( arc_angle ); double cnt = arcsegcount * 3600/std::abs( arc_angle );
@ -293,9 +269,8 @@ void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDs
} }
} }
transformArcToSegments( VECTOR2I( center.x, center.y ), arc->GetStart(), transformArcToSegments( VECTOR2I( center.x, center.y ), arc->GetStart(), arc_angle,
arc_angle, circlesegcount, circlesegcount, arc->GetWidth(), aDstContainer, *arc );
arc->GetWidth() + 2 * aClearanceValue, aDstContainer, *arc );
break; break;
} }
@ -306,13 +281,13 @@ void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDs
// Cannot add segments that have the same start and end point // Cannot add segments that have the same start and end point
if( Is_segment_a_circle( start3DU, end3DU ) ) if( Is_segment_a_circle( start3DU, end3DU ) )
{ {
const float radius = ((aTrack->GetWidth() / 2) + aClearanceValue) * m_biuTo3Dunits; const float radius = ( aTrack->GetWidth() / 2 ) * m_biuTo3Dunits;
aDstContainer->Add( new FILLED_CIRCLE_2D( start3DU, radius, *aTrack ) ); aDstContainer->Add( new FILLED_CIRCLE_2D( start3DU, radius, *aTrack ) );
} }
else else
{ {
const float width = (aTrack->GetWidth() + 2 * aClearanceValue ) * m_biuTo3Dunits; const float width = aTrack->GetWidth() * m_biuTo3Dunits;
aDstContainer->Add( new ROUND_SEGMENT_2D( start3DU, end3DU, width, *aTrack ) ); aDstContainer->Add( new ROUND_SEGMENT_2D( start3DU, end3DU, width, *aTrack ) );
} }
@ -326,20 +301,19 @@ void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDs
} }
void BOARD_ADAPTER::createPadWithClearance( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer, void BOARD_ADAPTER::createPadWithMargin( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayer, PCB_LAYER_ID aLayer, const VECTOR2I& aMargin ) const
const VECTOR2I& aClearanceValue ) const
{ {
SHAPE_POLY_SET poly; SHAPE_POLY_SET poly;
int maxError = GetBoard()->GetDesignSettings().m_MaxError; int maxError = GetBoard()->GetDesignSettings().m_MaxError;
VECTOR2I clearance = aClearanceValue; VECTOR2I clearance = aMargin;
// Our shape-based builder can't handle negative or differing x:y clearance values (the // Our shape-based builder can't handle negative or differing x:y clearance values (the
// former are common for solder paste while the later get generated when a relative paste // former are common for solder paste while the later get generated when a relative paste
// margin is used with an oblong pad). So we apply this huge hack and fake a larger pad to // margin is used with an oblong pad). So we apply this huge hack and fake a larger pad to
// run the general-purpose polygon builder on. // run the general-purpose polygon builder on.
// Of course being a hack it falls down when dealing with custom shape pads (where the size // Of course being a hack it falls down when dealing with custom shape pads (where the size
// is only the size of the anchor), so for those we punt and just use aClearanceValue.x. // is only the size of the anchor), so for those we punt and just use aMargin.x.
if( ( clearance.x < 0 || clearance.x != clearance.y ) if( ( clearance.x < 0 || clearance.x != clearance.y )
&& aPad->GetShape() != PAD_SHAPE::CUSTOM ) && aPad->GetShape() != PAD_SHAPE::CUSTOM )
@ -506,11 +480,9 @@ OBJECT_2D* BOARD_ADAPTER::createPadWithDrill( const PAD* aPad, int aInflateValue
} }
void BOARD_ADAPTER::addPadsWithClearance( const FOOTPRINT* aFootprint, void BOARD_ADAPTER::addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
CONTAINER_2D_BASE* aDstContainer, PCB_LAYER_ID aLayerId, bool aSkipNPTHPadsWihNoCopper,
PCB_LAYER_ID aLayerId, int aInflateValue, bool aSkipPlatedPads, bool aSkipNonPlatedPads )
bool aSkipNPTHPadsWihNoCopper, bool aSkipPlatedPads,
bool aSkipNonPlatedPads )
{ {
for( PAD* pad : aFootprint->Pads() ) for( PAD* pad : aFootprint->Pads() )
{ {
@ -556,7 +528,7 @@ void BOARD_ADAPTER::addPadsWithClearance( const FOOTPRINT* aFootprint,
if( aSkipNonPlatedPads && !isPlated ) if( aSkipNonPlatedPads && !isPlated )
continue; continue;
VECTOR2I margin( aInflateValue, aInflateValue ); VECTOR2I margin( 0, 0 );
switch( aLayerId ) switch( aLayerId )
{ {
@ -575,7 +547,7 @@ void BOARD_ADAPTER::addPadsWithClearance( const FOOTPRINT* aFootprint,
break; break;
} }
createPadWithClearance( pad, aDstContainer, aLayerId, margin ); createPadWithMargin( pad, aDstContainer, aLayerId, margin );
} }
} }
@ -648,16 +620,11 @@ void BOARD_ADAPTER::transformArcToSegments( const VECTOR2I& aCentre, const VECTO
} }
// Based on void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aDstContainer )
// TransformShapeWithClearanceToPolygon
// board_items_to_polygon_shape_transform.cpp#L431
void BOARD_ADAPTER::addShapeWithClearance( const PCB_SHAPE* aShape,
CONTAINER_2D_BASE* aDstContainer, PCB_LAYER_ID aLayerId,
int aClearanceValue )
{ {
// The full width of the lines to create // The full width of the lines to create
// The extra 1 protects the inner/outer radius values from degeneracy // The extra 1 protects the inner/outer radius values from degeneracy
const int linewidth = aShape->GetWidth() + ( 2 * aClearanceValue ) + 1; const int linewidth = aShape->GetWidth() + 1;
switch( aShape->GetShape() ) switch( aShape->GetShape() )
{ {
@ -684,7 +651,7 @@ void BOARD_ADAPTER::addShapeWithClearance( const PCB_SHAPE* aShape,
{ {
SHAPE_POLY_SET polyList; SHAPE_POLY_SET polyList;
aShape->TransformShapeWithClearanceToPolygon( polyList, aLayerId, 0, aShape->TransformShapeWithClearanceToPolygon( polyList, UNDEFINED_LAYER, 0,
ARC_HIGH_DEF, ERROR_INSIDE ); ARC_HIGH_DEF, ERROR_INSIDE );
polyList.Simplify( SHAPE_POLY_SET::PM_FAST ); polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
@ -746,7 +713,7 @@ void BOARD_ADAPTER::addShapeWithClearance( const PCB_SHAPE* aShape,
{ {
SHAPE_POLY_SET polyList; SHAPE_POLY_SET polyList;
aShape->TransformShapeWithClearanceToPolygon( polyList, aLayerId, 0, aShape->TransformShapeWithClearanceToPolygon( polyList, UNDEFINED_LAYER, 0,
ARC_HIGH_DEF, ERROR_INSIDE ); ARC_HIGH_DEF, ERROR_INSIDE );
polyList.Simplify( SHAPE_POLY_SET::PM_FAST ); polyList.Simplify( SHAPE_POLY_SET::PM_FAST );

View File

@ -247,7 +247,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
continue; continue;
// Add object item to layer container // Add object item to layer container
createTrack( track, layerContainer, 0.0f ); createTrack( track, layerContainer );
} }
} }
@ -529,11 +529,11 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
{ {
// Note: NPTH pads are not drawn on copper layers when the pad has the same shape // Note: NPTH pads are not drawn on copper layers when the pad has the same shape
// as its hole // as its hole
addPadsWithClearance( footprint, layerContainer, curr_layer_id, 0, true, addPads( footprint, layerContainer, curr_layer_id, true, renderPlatedPadsAsPlated,
renderPlatedPadsAsPlated, false ); false );
// Micro-wave footprints may have items on copper layers // Micro-wave footprints may have items on copper layers
addFootprintShapesWithClearance( footprint, layerContainer, curr_layer_id, 0 ); addFootprintShapes( footprint, layerContainer, curr_layer_id );
} }
} }
@ -542,9 +542,9 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// ADD PLATED PADS // ADD PLATED PADS
for( FOOTPRINT* footprint : m_board->Footprints() ) for( FOOTPRINT* footprint : m_board->Footprints() )
{ {
addPadsWithClearance( footprint, m_platedPadsFront, F_Cu, 0, true, false, true ); addPads( footprint, m_platedPadsFront, F_Cu, true, false, true );
addPadsWithClearance( footprint, m_platedPadsBack, B_Cu, 0, true, false, true ); addPads( footprint, m_platedPadsBack, B_Cu, true, false, true );
} }
m_platedPadsFront->BuildBVH(); m_platedPadsFront->BuildBVH();
@ -606,28 +606,25 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
switch( item->Type() ) switch( item->Type() )
{ {
case PCB_SHAPE_T: case PCB_SHAPE_T:
addShapeWithClearance( static_cast<PCB_SHAPE*>( item ), layerContainer, addShape( static_cast<PCB_SHAPE*>( item ), layerContainer );
curr_layer_id, 0 ); break;
break;
case PCB_TEXT_T: case PCB_TEXT_T:
addShapeWithClearance( static_cast<PCB_TEXT*>( item ), layerContainer, addShape( static_cast<PCB_TEXT*>( item ), layerContainer );
curr_layer_id, 0 ); break;
break;
case PCB_DIM_ALIGNED_T: case PCB_DIM_ALIGNED_T:
case PCB_DIM_CENTER_T: case PCB_DIM_CENTER_T:
case PCB_DIM_RADIAL_T: case PCB_DIM_RADIAL_T:
case PCB_DIM_ORTHOGONAL_T: case PCB_DIM_ORTHOGONAL_T:
case PCB_DIM_LEADER_T: case PCB_DIM_LEADER_T:
addShapeWithClearance( static_cast<PCB_DIMENSION_BASE*>( item ), addShape( static_cast<PCB_DIMENSION_BASE*>( item ), layerContainer );
layerContainer, curr_layer_id, 0 ); break;
break;
default: default:
wxLogTrace( m_logTrace, wxT( "createLayers: item type: %d not implemented" ), wxLogTrace( m_logTrace, wxT( "createLayers: item type: %d not implemented" ),
item->Type() ); item->Type() );
break; break;
} }
} }
} }
@ -914,13 +911,11 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
switch( item->Type() ) switch( item->Type() )
{ {
case PCB_SHAPE_T: case PCB_SHAPE_T:
addShapeWithClearance( static_cast<PCB_SHAPE*>( item ), layerContainer, addShape( static_cast<PCB_SHAPE*>( item ), layerContainer );
curr_layer_id, 0 );
break; break;
case PCB_TEXT_T: case PCB_TEXT_T:
addShapeWithClearance( static_cast<PCB_TEXT*>( item ), layerContainer, addShape( static_cast<PCB_TEXT*>( item ), layerContainer );
curr_layer_id, 0 );
break; break;
case PCB_DIM_ALIGNED_T: case PCB_DIM_ALIGNED_T:
@ -928,8 +923,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
case PCB_DIM_RADIAL_T: case PCB_DIM_RADIAL_T:
case PCB_DIM_ORTHOGONAL_T: case PCB_DIM_ORTHOGONAL_T:
case PCB_DIM_LEADER_T: case PCB_DIM_LEADER_T:
addShapeWithClearance( static_cast<PCB_DIMENSION_BASE*>( item ), layerContainer, addShape( static_cast<PCB_DIMENSION_BASE*>( item ), layerContainer );
curr_layer_id, 0 );
break; break;
default: default:
@ -981,11 +975,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
} }
else else
{ {
addPadsWithClearance( footprint, layerContainer, curr_layer_id, 0, addPads( footprint, layerContainer, curr_layer_id, false, false, false );
false, false, false );
} }
addFootprintShapesWithClearance( footprint, layerContainer, curr_layer_id, 0 ); addFootprintShapes( footprint, layerContainer, curr_layer_id );
} }

View File

@ -826,50 +826,28 @@ void EDA_TEXT::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControl
std::shared_ptr<SHAPE_COMPOUND> EDA_TEXT::GetEffectiveTextShape( ) const std::shared_ptr<SHAPE_COMPOUND> EDA_TEXT::GetEffectiveTextShape( ) const
{ {
std::shared_ptr<SHAPE_COMPOUND> shape = std::make_shared<SHAPE_COMPOUND>(); std::shared_ptr<SHAPE_COMPOUND> shape = std::make_shared<SHAPE_COMPOUND>();
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
KIFONT::FONT* font = GetDrawFont(); KIFONT::FONT* font = GetDrawFont();
wxSize size = GetTextSize();
int penWidth = GetEffectiveTextPenWidth(); int penWidth = GetEffectiveTextPenWidth();
bool forceBold = true;
if( IsMirrored() ) CALLBACK_GAL callback_gal( empty_opts,
size.x = -size.x; // Stroke callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{
shape->AddShape( new SHAPE_SEGMENT( aPt1, aPt2, penWidth ) );
},
// Triangulation callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
{
SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
wxArrayString strings_list; for( const VECTOR2I& point : { aPt1, aPt2, aPt3 } )
std::vector<VECTOR2I> positions; triShape->Append( point.x, point.y );
if( IsMultilineAllowed() ) shape->AddShape( triShape );
{ } );
wxStringSplit( GetShownText(), strings_list, wxChar('\n') );
positions.reserve( strings_list.Count() );
GetLinePositions( positions, strings_list.Count() );
}
else
{
strings_list.Add( GetShownText() );
positions.push_back( GetDrawPos() );
}
for( unsigned ii = 0; ii < strings_list.Count(); ii++ ) font->Draw( &callback_gal, GetShownText(), GetTextPos(), GetAttributes() );
{
GRText( positions[ii], strings_list.Item( ii ), GetDrawRotation(), size,
GetDrawHorizJustify(), GetDrawVertJustify(), penWidth, IsItalic(), forceBold, font,
// Stroke callback
[&]( const VECTOR2D& aPt1, const VECTOR2D& aPt2 )
{
shape->AddShape( new SHAPE_SEGMENT( aPt1, aPt2, penWidth ) );
},
// Triangulation callback
[&]( const VECTOR2D& aPt1, const VECTOR2D& aPt2, const VECTOR2D& aPt3 )
{
SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
triShape->Append( aPt1 );
triShape->Append( aPt2 );
triShape->Append( aPt3 );
shape->AddShape( triShape );
} );
}
return shape; return shape;
} }

View File

@ -129,7 +129,8 @@ void GRPrintText( wxDC* aDC, const VECTOR2I& aPos, const COLOR4D& aColor, const
enum GR_TEXT_H_ALIGN_T aH_justify, enum GR_TEXT_V_ALIGN_T aV_justify, enum GR_TEXT_H_ALIGN_T aH_justify, enum GR_TEXT_V_ALIGN_T aV_justify,
int aWidth, bool aItalic, bool aBold, KIFONT::FONT* aFont ) int aWidth, bool aItalic, bool aBold, KIFONT::FONT* aFont )
{ {
bool fill_mode = true; KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
bool fill_mode = true;
if( !aFont ) if( !aFont )
aFont = KIFONT::FONT::GetFont(); aFont = KIFONT::FONT::GetFont();
@ -143,7 +144,7 @@ void GRPrintText( wxDC* aDC, const VECTOR2I& aPos, const COLOR4D& aColor, const
fill_mode = false; fill_mode = false;
} }
GRText( aPos, aText, aOrient, aSize, aH_justify, aV_justify, aWidth, aItalic, aBold, aFont, CALLBACK_GAL callback_gal( empty_opts,
// Stroke callback // Stroke callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 ) [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{ {
@ -158,48 +159,6 @@ void GRPrintText( wxDC* aDC, const VECTOR2I& aPos, const COLOR4D& aColor, const
VECTOR2I pts[3] = { aPt1, aPt2, aPt3 }; VECTOR2I pts[3] = { aPt1, aPt2, aPt3 };
GRClosedPoly( nullptr, aDC, 3, pts, true, 0, aColor, aColor ); GRClosedPoly( nullptr, aDC, 3, pts, true, 0, aColor, aColor );
} ); } );
}
/**
* De-compose graphic text into either strokes and/or triangles.
*
* @param aPos is the text position (according to h_justify, v_justify).
* @param aText is the text to draw.
* @param aOrient is the angle.
* @param aSize is the text size (size.x or size.y can be < 0 for mirrored texts).
* @param aH_justify is the horizontal justification (Left, center, right).
* @param aV_justify is the vertical justification (bottom, center, top).
* @param aWidth is the line width (pen width) (use default width if aWidth = 0).
* if width < 0 : draw segments in sketch mode, width = abs(width)
* Use a value min(aSize.x, aSize.y) / 5 for a bold text.
* @param aItalic is the true to simulate an italic font.
* @param aBold use true to use a bold font. Useful only with default width value (aWidth = 0).
* @param aFont is the font to use, or nullptr for the KiCad stroke font
* @param aStrokeCallback is a two-point stroking callback
* @param aTriangleCallback is a three-point triangulation callback
*/
void GRText( const VECTOR2I& aPos, const wxString& aText, const EDA_ANGLE& aOrient,
const VECTOR2I& aSize, enum GR_TEXT_H_ALIGN_T aH_justify,
enum GR_TEXT_V_ALIGN_T aV_justify, int aWidth, bool aItalic, bool aBold,
KIFONT::FONT* aFont,
std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2 )> aStrokeCallback,
std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2,
const VECTOR2I& aPt3 )> aTriangleCallback )
{
if( !aFont )
aFont = KIFONT::FONT::GetFont();
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
CALLBACK_GAL callback_gal( empty_opts, aStrokeCallback, aTriangleCallback );
if( aWidth == 0 && aBold ) // Use default values if aWidth == 0
aWidth = GetPenSizeForBold( std::min( aSize.x, aSize.y ) );
if( aWidth < 0 )
aWidth = -aWidth;
TEXT_ATTRIBUTES attributes; TEXT_ATTRIBUTES attributes;
attributes.m_Angle = aOrient; attributes.m_Angle = aOrient;
@ -209,15 +168,7 @@ void GRText( const VECTOR2I& aPos, const wxString& aText, const EDA_ANGLE& aOrie
attributes.m_Halign = aH_justify; attributes.m_Halign = aH_justify;
attributes.m_Valign = aV_justify; attributes.m_Valign = aV_justify;
VECTOR2D size = aSize; aFont->Draw( &callback_gal, aText, aPos, attributes );
attributes.m_Mirrored = size.x < 0;
if( size.x < 0 )
size.x = - size.x;
attributes.m_Size = size;
aFont->Draw( &callback_gal, aText, VECTOR2D( aPos ), attributes );
} }

View File

@ -42,6 +42,7 @@
#include <plotters/plotter.h> #include <plotters/plotter.h>
#include <geometry/shape_line_chain.h> #include <geometry/shape_line_chain.h>
#include <bezier_curves.h> #include <bezier_curves.h>
#include <callback_gal.h>
#include <math/util.h> // for KiROUND #include <math/util.h> // for KiROUND
@ -666,6 +667,8 @@ void PLOTTER::Text( const VECTOR2I& aPos,
KIFONT::FONT* aFont, KIFONT::FONT* aFont,
void* aData ) void* aData )
{ {
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
SetColor( aColor ); SetColor( aColor );
SetCurrentLineWidth( aPenWidth, aData ); SetCurrentLineWidth( aPenWidth, aData );
@ -675,7 +678,7 @@ void PLOTTER::Text( const VECTOR2I& aPos,
if( aPenWidth < 0 ) if( aPenWidth < 0 )
aPenWidth = -aPenWidth; aPenWidth = -aPenWidth;
GRText( aPos, aText, aOrient, aSize, aH_justify, aV_justify, aPenWidth, aItalic, aBold, aFont, CALLBACK_GAL callback_gal( empty_opts,
// Stroke callback // Stroke callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 ) [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{ {
@ -694,4 +697,14 @@ void PLOTTER::Text( const VECTOR2I& aPos,
PlotPoly( cornerList, FILL_T::FILLED_SHAPE, 0, aData ); PlotPoly( cornerList, FILL_T::FILLED_SHAPE, 0, aData );
} ); } );
TEXT_ATTRIBUTES attributes;
attributes.m_Angle = aOrient;
attributes.m_StrokeWidth = aPenWidth;
attributes.m_Italic = aItalic;
attributes.m_Bold = aBold;
attributes.m_Halign = aH_justify;
attributes.m_Valign = aV_justify;
aFont->Draw( &callback_gal, aText, aPos, attributes );
} }

View File

@ -110,32 +110,5 @@ void GRPrintText( wxDC* aDC, const VECTOR2I& aPos, const KIGFX::COLOR4D& aColor,
enum GR_TEXT_H_ALIGN_T aH_justify, enum GR_TEXT_V_ALIGN_T aV_justify, enum GR_TEXT_H_ALIGN_T aH_justify, enum GR_TEXT_V_ALIGN_T aV_justify,
int aWidth, bool aItalic, bool aBold, KIFONT::FONT* aFont ); int aWidth, bool aItalic, bool aBold, KIFONT::FONT* aFont );
/**
* De-compose graphic text into either strokes and/or triangles.
*
* @param aPos is the text position (according to h_justify, v_justify).
* @param aText is the text to draw.
* @param aOrient is the angle.
* @param aSize is the text size (size.x or size.y can be < 0 for mirrored texts).
* @param aH_justify is the horizontal justification (Left, center, right).
* @param aV_justify is the vertical justification (bottom, center, top).
* @param aWidth is the line width (pen width) (use default width if aWidth = 0).
* if width < 0 : draw segments in sketch mode, width = abs(width)
* Use a value min(aSize.x, aSize.y) / 5 for a bold text.
* @param aItalic is the true to simulate an italic font.
* @param aBold use true to use a bold font. Useful only with default width value (aWidth = 0).
* @param aFont is the font to use, or nullptr for the KiCad stroke font
* @param aStrokeCallback is a two-point stroking callback
* @param aTriangleCallback is a three-point triangulation callback
*/
void GRText( const VECTOR2I& aPos, const wxString& aText, const EDA_ANGLE& aOrient,
const VECTOR2I& aSize, enum GR_TEXT_H_ALIGN_T aH_justify,
enum GR_TEXT_V_ALIGN_T aV_justify, int aWidth, bool aItalic, bool aBold,
KIFONT::FONT* aFont,
std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2 )> aStrokeCallback,
std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2,
const VECTOR2I& aPt3 )> aTriangleCallback );
#endif /* GR_TEXT_H */ #endif /* GR_TEXT_H */

View File

@ -35,6 +35,7 @@
#include <string_utils.h> #include <string_utils.h>
#include <painter.h> #include <painter.h>
#include <geometry/shape_compound.h> #include <geometry/shape_compound.h>
#include <callback_gal.h>
#include <convert_basic_shapes_to_polygon.h> #include <convert_basic_shapes_to_polygon.h>
FP_TEXT::FP_TEXT( FOOTPRINT* aParentFootprint, TEXT_TYPE text_type ) : FP_TEXT::FP_TEXT( FOOTPRINT* aParentFootprint, TEXT_TYPE text_type ) :
@ -465,14 +466,11 @@ void FP_TEXT::TransformTextShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerB
PCB_LAYER_ID aLayer, int aClearance, PCB_LAYER_ID aLayer, int aClearance,
int aError, ERROR_LOC aErrorLoc ) const int aError, ERROR_LOC aErrorLoc ) const
{ {
wxSize size = GetTextSize(); KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
int penWidth = GetEffectiveTextPenWidth(); KIFONT::FONT* font = GetDrawFont();
int penWidth = GetEffectiveTextPenWidth();
if( IsMirrored() ) CALLBACK_GAL callback_gal( empty_opts,
size.x = -size.x;
GRText( GetTextPos(), GetShownText(), GetDrawRotation(), size, GetHorizJustify(),
GetVertJustify(), penWidth, IsItalic(), IsBold(), GetDrawFont(),
// Stroke callback // Stroke callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 ) [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{ {
@ -487,6 +485,8 @@ void FP_TEXT::TransformTextShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerB
for( const VECTOR2I& point : { aPt1, aPt2, aPt3 } ) for( const VECTOR2I& point : { aPt1, aPt2, aPt3 } )
aCornerBuffer.Append( point.x, point.y ); aCornerBuffer.Append( point.x, point.y );
} ); } );
font->Draw( &callback_gal, GetShownText(), GetTextPos(), GetAttributes() );
} }

View File

@ -36,6 +36,7 @@
#include <trigo.h> #include <trigo.h>
#include <string_utils.h> #include <string_utils.h>
#include <geometry/shape_compound.h> #include <geometry/shape_compound.h>
#include <callback_gal.h>
#include <convert_basic_shapes_to_polygon.h> #include <convert_basic_shapes_to_polygon.h>
using KIGFX::PCB_RENDER_SETTINGS; using KIGFX::PCB_RENDER_SETTINGS;
@ -230,15 +231,11 @@ void PCB_TEXT::TransformTextShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCorner
PCB_LAYER_ID aLayer, int aClearance, PCB_LAYER_ID aLayer, int aClearance,
int aError, ERROR_LOC aErrorLoc ) const int aError, ERROR_LOC aErrorLoc ) const
{ {
wxSize size = GetTextSize(); KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
KIFONT::FONT* font = GetDrawFont();
int penWidth = GetEffectiveTextPenWidth();
if( IsMirrored() ) CALLBACK_GAL callback_gal( empty_opts,
size.x = -size.x;
int penWidth = GetEffectiveTextPenWidth();
GRText( GetTextPos(), GetShownText(), GetTextAngle(), size, GetHorizJustify(),
GetVertJustify(), penWidth, IsItalic(), IsBold(), GetDrawFont(),
// Stroke callback // Stroke callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 ) [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{ {
@ -253,6 +250,8 @@ void PCB_TEXT::TransformTextShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCorner
for( const VECTOR2I& point : { aPt1, aPt2, aPt3 } ) for( const VECTOR2I& point : { aPt1, aPt2, aPt3 } )
aCornerBuffer.Append( point.x, point.y ); aCornerBuffer.Append( point.x, point.y );
} ); } );
font->Draw( &callback_gal, GetShownText(), GetTextPos(), GetAttributes() );
} }