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();
// Helper functions to create the board
void createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer,
int aClearanceValue );
void createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer );
void createPadWithClearance( const PAD *aPad, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayer, const VECTOR2I& aClearanceValue ) const;
void createPadWithMargin( const PAD *aPad, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayer, const VECTOR2I& aMargin ) const;
OBJECT_2D* createPadWithDrill( const PAD* aPad, int aInflateValue );
void addPadsWithClearance( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId, int aInflateValue,
bool aSkipNPTHPadsWihNoCopper, bool aSkipPlatedPads,
void addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId, bool aSkipNPTHPadsWihNoCopper, bool aSkipPlatedPads,
bool aSkipNonPlatedPads );
void addFootprintShapesWithClearance( const FOOTPRINT* aFootprint,
CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId, int aInflateValue );
void addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId );
void addShapeWithClearance( const PCB_TEXT* aText, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId, int aClearanceValue );
void addShape( const PCB_TEXT* aText, CONTAINER_2D_BASE* aDstContainer );
void addShapeWithClearance( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId, int aClearanceValue );
void addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aDstContainer );
void addShapeWithClearance( const PCB_DIMENSION_BASE* aDimension,
CONTAINER_2D_BASE* aDstContainer, PCB_LAYER_ID aLayerId,
int aClearanceValue );
void addShape( const PCB_DIMENSION_BASE* aDimension, CONTAINER_2D_BASE* aDstContainer );
void addSolidAreasShapes( const ZONE* aZoneContainer, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId );

View File

@ -49,50 +49,31 @@
#include <geometry/shape_circle.h>
#include <geometry/shape_rect.h>
#include <geometry/shape_simple.h>
#include <gr_text.h>
#include <utility>
#include <vector>
#include <wx/log.h>
#include <macros.h>
#include <callback_gal.h>
// 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 )
void BOARD_ADAPTER::addShape( const PCB_TEXT* aText, CONTAINER_2D_BASE* aDstContainer )
{
VECTOR2I size = aText->GetTextSize();
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
KIFONT::FONT* font = aText->GetDrawFont();
int penWidth = aText->GetEffectiveTextPenWidth() * m_biuTo3Dunits;
if( aText->IsMirrored() )
size.x = -size.x;
// 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(),
CALLBACK_GAL callback_gal( empty_opts,
// Stroke callback
[&]( 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 );
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( start3DU, end3DU ) )
{
aDstContainer->Add( new FILLED_CIRCLE_2D( start3DU,
adjustedWidth * m_biuTo3Dunits / 2,
*aText ) );
}
if( Is_segment_a_circle( a3DU, b3DU ) )
aDstContainer->Add( new FILLED_CIRCLE_2D( a3DU, penWidth / 2, *aText ) );
else
{
aDstContainer->Add( new ROUND_SEGMENT_2D( start3DU, end3DU,
adjustedWidth * m_biuTo3Dunits,
*aText ) );
}
aDstContainer->Add( new ROUND_SEGMENT_2D( a3DU, b3DU, penWidth, *aText ) );
},
// Triangulation callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
{
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 ) );
} );
font->Draw( &callback_gal, aText->GetShownText(), aText->GetTextPos(), aText->GetAttributes() );
}
void BOARD_ADAPTER::addShapeWithClearance( const PCB_DIMENSION_BASE* aDimension,
CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId, int aClearanceValue )
void BOARD_ADAPTER::addShape( const PCB_DIMENSION_BASE* aDimension,
CONTAINER_2D_BASE* aDstContainer )
{
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() )
{
@ -119,9 +101,7 @@ void BOARD_ADAPTER::addShapeWithClearance( const PCB_DIMENSION_BASE* aDimension,
case SH_SEGMENT:
{
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 end3DU ( seg.B.x * m_biuTo3Dunits, -seg.B.y * m_biuTo3Dunits );
aDstContainer->Add( new ROUND_SEGMENT_2D( start3DU, end3DU, linewidth * m_biuTo3Dunits,
@ -132,13 +112,13 @@ void BOARD_ADAPTER::addShapeWithClearance( const PCB_DIMENSION_BASE* aDimension,
case SH_CIRCLE:
{
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,
shape->Centre().y * m_biuTo3Dunits );
aDstContainer->Add( new RING_2D( center, ( radius - deltar ) * m_biuTo3Dunits,
( radius + deltar ) * m_biuTo3Dunits, *aDimension ) );
aDstContainer->Add( new RING_2D( center, ( radius - delta ) * m_biuTo3Dunits,
( radius + delta ) * m_biuTo3Dunits, *aDimension ) );
break;
}
@ -150,14 +130,41 @@ void BOARD_ADAPTER::addShapeWithClearance( const PCB_DIMENSION_BASE* aDimension,
}
// Based on
// void FOOTPRINT::TransformFPShapesWithClearanceToPolygonSet
// 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 )
void BOARD_ADAPTER::addFootprintShapes( const FOOTPRINT* aFootprint,
CONTAINER_2D_BASE* aDstContainer, PCB_LAYER_ID aLayerId )
{
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() )
{
@ -168,7 +175,7 @@ void BOARD_ADAPTER::addFootprintShapesWithClearance( const FOOTPRINT* aFootprint
FP_TEXT* text = static_cast<FP_TEXT*>( item );
if( text->GetLayer() == aLayerId && text->IsVisible() )
texts.push_back( text );
textItems.push_back( text );
break;
}
@ -182,7 +189,7 @@ void BOARD_ADAPTER::addFootprintShapesWithClearance( const FOOTPRINT* aFootprint
PCB_DIMENSION_BASE* dimension = static_cast<PCB_DIMENSION_BASE*>( item );
if( dimension->GetLayer() == aLayerId )
addShapeWithClearance( dimension, aDstContainer, aLayerId, 0 );
addShape( dimension, aDstContainer );
break;
}
@ -192,7 +199,7 @@ void BOARD_ADAPTER::addFootprintShapesWithClearance( const FOOTPRINT* aFootprint
FP_SHAPE* shape = static_cast<FP_SHAPE*>( item );
if( shape->GetLayer() == aLayerId )
addShapeWithClearance( (const PCB_SHAPE*) shape, aDstContainer, aLayerId, 0 );
addShape( static_cast<const PCB_SHAPE*>( shape ), aDstContainer );
break;
}
@ -202,53 +209,20 @@ void BOARD_ADAPTER::addFootprintShapesWithClearance( const FOOTPRINT* aFootprint
}
}
// Convert texts for footprints
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 )
for( FP_TEXT* text : textItems )
{
VECTOR2I size = text->GetTextSize();
int penWidth = text->GetEffectiveTextPenWidth();
int adjustedWidth = penWidth + ( 2 * aInflateValue );
textItem = text;
penWidth = textItem->GetEffectiveTextPenWidth() * m_biuTo3Dunits;
if( text->IsMirrored() )
size.x = -size.x;
KIFONT::FONT* font = textItem->GetDrawFont();
GRText( text->GetTextPos(), text->GetShownText(), text->GetTextAngle(), size,
text->GetHorizJustify(), text->GetVertJustify(), penWidth, text->IsItalic(),
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
} );
font->Draw( &callback_gal, textItem->GetShownText(), textItem->GetTextPos(),
textItem->GetAttributes() );
}
}
void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer,
int aClearanceValue )
void BOARD_ADAPTER::createTrack( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer )
{
SFVEC2F start3DU( aTrack->GetStart().x * m_biuTo3Dunits,
-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:
{
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 ) );
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
// radius very big. so we calculate a reasonable value for circlesegcount.
if( arcsegcount <= 1 ) // The arc will be approximated by a segment
{
circlesegcount = 1;
}
else
{
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(),
arc_angle, circlesegcount,
arc->GetWidth() + 2 * aClearanceValue, aDstContainer, *arc );
transformArcToSegments( VECTOR2I( center.x, center.y ), arc->GetStart(), arc_angle,
circlesegcount, arc->GetWidth(), aDstContainer, *arc );
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
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 ) );
}
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 ) );
}
@ -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,
PCB_LAYER_ID aLayer,
const VECTOR2I& aClearanceValue ) const
void BOARD_ADAPTER::createPadWithMargin( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayer, const VECTOR2I& aMargin ) const
{
SHAPE_POLY_SET poly;
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
// 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
// run the general-purpose polygon builder on.
// 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 )
&& 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,
CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId, int aInflateValue,
bool aSkipNPTHPadsWihNoCopper, bool aSkipPlatedPads,
bool aSkipNonPlatedPads )
void BOARD_ADAPTER::addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId, bool aSkipNPTHPadsWihNoCopper,
bool aSkipPlatedPads, bool aSkipNonPlatedPads )
{
for( PAD* pad : aFootprint->Pads() )
{
@ -556,7 +528,7 @@ void BOARD_ADAPTER::addPadsWithClearance( const FOOTPRINT* aFootprint,
if( aSkipNonPlatedPads && !isPlated )
continue;
VECTOR2I margin( aInflateValue, aInflateValue );
VECTOR2I margin( 0, 0 );
switch( aLayerId )
{
@ -575,7 +547,7 @@ void BOARD_ADAPTER::addPadsWithClearance( const FOOTPRINT* aFootprint,
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
// 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 )
void BOARD_ADAPTER::addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aDstContainer )
{
// The full width of the lines to create
// 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() )
{
@ -684,7 +651,7 @@ void BOARD_ADAPTER::addShapeWithClearance( const PCB_SHAPE* aShape,
{
SHAPE_POLY_SET polyList;
aShape->TransformShapeWithClearanceToPolygon( polyList, aLayerId, 0,
aShape->TransformShapeWithClearanceToPolygon( polyList, UNDEFINED_LAYER, 0,
ARC_HIGH_DEF, ERROR_INSIDE );
polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
@ -746,7 +713,7 @@ void BOARD_ADAPTER::addShapeWithClearance( const PCB_SHAPE* aShape,
{
SHAPE_POLY_SET polyList;
aShape->TransformShapeWithClearanceToPolygon( polyList, aLayerId, 0,
aShape->TransformShapeWithClearanceToPolygon( polyList, UNDEFINED_LAYER, 0,
ARC_HIGH_DEF, ERROR_INSIDE );
polyList.Simplify( SHAPE_POLY_SET::PM_FAST );

View File

@ -247,7 +247,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
continue;
// 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
// as its hole
addPadsWithClearance( footprint, layerContainer, curr_layer_id, 0, true,
renderPlatedPadsAsPlated, false );
addPads( footprint, layerContainer, curr_layer_id, true, renderPlatedPadsAsPlated,
false );
// 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
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();
@ -606,13 +606,11 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
switch( item->Type() )
{
case PCB_SHAPE_T:
addShapeWithClearance( static_cast<PCB_SHAPE*>( item ), layerContainer,
curr_layer_id, 0 );
addShape( static_cast<PCB_SHAPE*>( item ), layerContainer );
break;
case PCB_TEXT_T:
addShapeWithClearance( static_cast<PCB_TEXT*>( item ), layerContainer,
curr_layer_id, 0 );
addShape( static_cast<PCB_TEXT*>( item ), layerContainer );
break;
case PCB_DIM_ALIGNED_T:
@ -620,8 +618,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
case PCB_DIM_RADIAL_T:
case PCB_DIM_ORTHOGONAL_T:
case PCB_DIM_LEADER_T:
addShapeWithClearance( static_cast<PCB_DIMENSION_BASE*>( item ),
layerContainer, curr_layer_id, 0 );
addShape( static_cast<PCB_DIMENSION_BASE*>( item ), layerContainer );
break;
default:
@ -914,13 +911,11 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
switch( item->Type() )
{
case PCB_SHAPE_T:
addShapeWithClearance( static_cast<PCB_SHAPE*>( item ), layerContainer,
curr_layer_id, 0 );
addShape( static_cast<PCB_SHAPE*>( item ), layerContainer );
break;
case PCB_TEXT_T:
addShapeWithClearance( static_cast<PCB_TEXT*>( item ), layerContainer,
curr_layer_id, 0 );
addShape( static_cast<PCB_TEXT*>( item ), layerContainer );
break;
case PCB_DIM_ALIGNED_T:
@ -928,8 +923,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
case PCB_DIM_RADIAL_T:
case PCB_DIM_ORTHOGONAL_T:
case PCB_DIM_LEADER_T:
addShapeWithClearance( static_cast<PCB_DIMENSION_BASE*>( item ), layerContainer,
curr_layer_id, 0 );
addShape( static_cast<PCB_DIMENSION_BASE*>( item ), layerContainer );
break;
default:
@ -981,11 +975,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
}
else
{
addPadsWithClearance( footprint, layerContainer, curr_layer_id, 0,
false, false, false );
addPads( footprint, layerContainer, curr_layer_id, 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> shape = std::make_shared<SHAPE_COMPOUND>();
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
KIFONT::FONT* font = GetDrawFont();
wxSize size = GetTextSize();
int penWidth = GetEffectiveTextPenWidth();
bool forceBold = true;
if( IsMirrored() )
size.x = -size.x;
wxArrayString strings_list;
std::vector<VECTOR2I> positions;
if( IsMultilineAllowed() )
{
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++ )
{
GRText( positions[ii], strings_list.Item( ii ), GetDrawRotation(), size,
GetDrawHorizJustify(), GetDrawVertJustify(), penWidth, IsItalic(), forceBold, font,
CALLBACK_GAL callback_gal( empty_opts,
// Stroke callback
[&]( const VECTOR2D& aPt1, const VECTOR2D& aPt2 )
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{
shape->AddShape( new SHAPE_SEGMENT( aPt1, aPt2, penWidth ) );
},
// Triangulation callback
[&]( const VECTOR2D& aPt1, const VECTOR2D& aPt2, const VECTOR2D& aPt3 )
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
{
SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
triShape->Append( aPt1 );
triShape->Append( aPt2 );
triShape->Append( aPt3 );
for( const VECTOR2I& point : { aPt1, aPt2, aPt3 } )
triShape->Append( point.x, point.y );
shape->AddShape( triShape );
} );
}
font->Draw( &callback_gal, GetShownText(), GetTextPos(), GetAttributes() );
return shape;
}

View File

@ -129,6 +129,7 @@ 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,
int aWidth, bool aItalic, bool aBold, KIFONT::FONT* aFont )
{
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
bool fill_mode = true;
if( !aFont )
@ -143,7 +144,7 @@ void GRPrintText( wxDC* aDC, const VECTOR2I& aPos, const COLOR4D& aColor, const
fill_mode = false;
}
GRText( aPos, aText, aOrient, aSize, aH_justify, aV_justify, aWidth, aItalic, aBold, aFont,
CALLBACK_GAL callback_gal( empty_opts,
// Stroke callback
[&]( 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 };
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;
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_Valign = aV_justify;
VECTOR2D size = aSize;
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 );
aFont->Draw( &callback_gal, aText, aPos, attributes );
}

View File

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

View File

@ -35,6 +35,7 @@
#include <string_utils.h>
#include <painter.h>
#include <geometry/shape_compound.h>
#include <callback_gal.h>
#include <convert_basic_shapes_to_polygon.h>
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,
int aError, ERROR_LOC aErrorLoc ) const
{
wxSize size = GetTextSize();
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
KIFONT::FONT* font = GetDrawFont();
int penWidth = GetEffectiveTextPenWidth();
if( IsMirrored() )
size.x = -size.x;
GRText( GetTextPos(), GetShownText(), GetDrawRotation(), size, GetHorizJustify(),
GetVertJustify(), penWidth, IsItalic(), IsBold(), GetDrawFont(),
CALLBACK_GAL callback_gal( empty_opts,
// Stroke callback
[&]( 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 } )
aCornerBuffer.Append( point.x, point.y );
} );
font->Draw( &callback_gal, GetShownText(), GetTextPos(), GetAttributes() );
}

View File

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