Outline font rendering for Cairo, plotter, printer and 3D viewer.

Fixes https://gitlab.com/kicad/code/kicad/issues/10319
This commit is contained in:
Jeff Young 2022-01-10 01:53:01 +00:00
parent 931702347a
commit 7d032f9c2f
27 changed files with 491 additions and 720 deletions

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2022 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
@ -56,38 +56,6 @@
#include <macros.h>
struct CALLBACK_DATA
{
const BOARD_ITEM* m_BoardItem;
CONTAINER_2D_BASE* m_Container;
int m_TextWidth;
float m_BiuTo3Dunits;
};
// This is a call back function, used by GRText to draw the 3D text shape:
void addTextSegmToContainer( int x0, int y0, int xf, int yf, void* aData )
{
CALLBACK_DATA* data = static_cast<CALLBACK_DATA*>( aData );
const SFVEC2F start3DU( x0 * data->m_BiuTo3Dunits, -y0 * data->m_BiuTo3Dunits );
const SFVEC2F end3DU ( xf * data->m_BiuTo3Dunits, -yf * data->m_BiuTo3Dunits );
if( Is_segment_a_circle( start3DU, end3DU ) )
{
data->m_Container->Add( new FILLED_CIRCLE_2D( start3DU,
data->m_TextWidth * data->m_BiuTo3Dunits / 2,
*data->m_BoardItem ) );
}
else
{
data->m_Container->Add( new ROUND_SEGMENT_2D( start3DU, end3DU,
data->m_TextWidth * data->m_BiuTo3Dunits,
*data->m_BoardItem ) );
}
}
// Based on
// void PCB_TEXT::TransformTextShapeWithClearanceToPolygon
// board_items_to_polygon_shape_transform.cpp
@ -99,23 +67,40 @@ void BOARD_ADAPTER::addShapeWithClearance( const PCB_TEXT* aText, CONTAINER_2D_B
if( aText->IsMirrored() )
size.x = -size.x;
CALLBACK_DATA callbackData;
callbackData.m_BoardItem = aText;
callbackData.m_Container = aDstContainer;
callbackData.m_TextWidth = aText->GetEffectiveTextPenWidth() + ( 2 * aClearanceValue );
callbackData.m_BiuTo3Dunits = m_biuTo3Dunits;
// not actually used, but needed by GRText
const COLOR4D dummy_color;
// Use the actual text width to generate segments. The segment position depend on
// text thickness and justification
bool isBold = aText->IsBold();
int penWidth = aText->GetEffectiveTextPenWidth();
int adjustedWidth = penWidth + ( 2 * aClearanceValue );
GRText( nullptr, aText->GetTextPos(), dummy_color, aText->GetShownText(), aText->GetTextAngle(),
size, aText->GetHorizJustify(), aText->GetVertJustify(), penWidth, aText->IsItalic(),
isBold, aText->GetDrawFont(), addTextSegmToContainer, &callbackData );
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 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,
*aText ) );
}
else
{
aDstContainer->Add( new ROUND_SEGMENT_2D( start3DU, end3DU,
adjustedWidth * m_biuTo3Dunits,
*aText ) );
}
},
[&]( 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, *aText ) );
} );
}
@ -161,9 +146,7 @@ void BOARD_ADAPTER::addShapeWithClearance( const PCB_DIMENSION_BASE* aDimension,
default:
break;
}
}
}
@ -228,22 +211,38 @@ void BOARD_ADAPTER::addFootprintShapesWithClearance( const FOOTPRINT* aFootprint
for( FP_TEXT* text : texts )
{
CALLBACK_DATA callbackData;
callbackData.m_BoardItem = &aFootprint->Value();
callbackData.m_Container = aDstContainer;
callbackData.m_BiuTo3Dunits = m_biuTo3Dunits;
callbackData.m_TextWidth = text->GetEffectiveTextPenWidth() + ( 2 * aInflateValue );
VECTOR2I size = text->GetTextSize();
bool isBold = text->IsBold();
int penWidth = text->GetEffectiveTextPenWidth();
int adjustedWidth = penWidth + ( 2 * aInflateValue );
if( text->IsMirrored() )
size.x = -size.x;
GRText( nullptr, text->GetTextPos(), BLACK, text->GetShownText(), text->GetDrawRotation(),
size, text->GetHorizJustify(), text->GetVertJustify(), penWidth, text->IsItalic(),
isBold, text->GetDrawFont(), addTextSegmToContainer, &callbackData );
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
} );
}
}

View File

@ -21,7 +21,7 @@ include_directories(
set( GAL_SRCS
# Common part
basic_gal.cpp
callback_gal.cpp
draw_panel_gal.cpp
gl_context_mgr.cpp
newstroke_font.cpp

View File

@ -1,183 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2021 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
*/
/**
* Implement a very basic GAL used to draw, plot and convert texts in segments
* for DRC functions, using the common GAL functions.
* Draw functions use wxDC.
* Plot functions use a PLOTTER
* Convert texts in segments use a callback function created by the caller
* @file basic_gal.cpp
*/
#include <gr_basic.h>
#include <plotters/plotter.h>
#include <trigo.h>
#include <basic_gal.h>
using namespace KIGFX;
KIGFX::GAL_DISPLAY_OPTIONS basic_displayOptions;
// the basic GAL doesn't get an external display option object
BASIC_GAL basic_gal( basic_displayOptions );
const VECTOR2D BASIC_GAL::transform( const VECTOR2D& aPoint ) const
{
VECTOR2D point = aPoint + m_transform.m_moveOffset - m_transform.m_rotCenter;
point = point.Rotate( m_transform.m_rotAngle ) + m_transform.m_rotCenter;
return point;
}
void BASIC_GAL::doDrawPolyline( const std::vector<VECTOR2I>& aLocalPointList )
{
if( m_DC )
{
if( m_isFillEnabled )
{
GRPoly( m_isClipped ? &m_clipBox : nullptr, m_DC, aLocalPointList.size(),
&aLocalPointList[0], 0, GetLineWidth(), m_Color, m_Color );
}
else
{
for( unsigned ii = 1; ii < aLocalPointList.size(); ++ii )
{
GRCSegm( m_isClipped ? &m_clipBox : nullptr, m_DC, aLocalPointList[ ii - 1],
aLocalPointList[ii], GetLineWidth(), m_Color );
}
}
}
else if( m_plotter )
{
m_plotter->MoveTo( aLocalPointList[0] );
for( unsigned ii = 1; ii < aLocalPointList.size(); ii++ )
{
m_plotter->LineTo( aLocalPointList[ii] );
}
m_plotter->PenFinish();
}
else if( m_callback )
{
for( unsigned ii = 1; ii < aLocalPointList.size(); ii++ )
{
m_callback( aLocalPointList[ ii - 1].x, aLocalPointList[ ii - 1].y,
aLocalPointList[ii].x, aLocalPointList[ii].y, m_callbackData );
}
}
}
void BASIC_GAL::DrawPolyline( const std::deque<VECTOR2D>& aPointList )
{
if( aPointList.size() < 2 )
return;
std::vector<VECTOR2I> polyline_corners;
for( const VECTOR2D& pt : aPointList )
polyline_corners.emplace_back( (VECTOR2I) transform( pt ) );
doDrawPolyline( polyline_corners );
}
void BASIC_GAL::DrawPolyline( const std::vector<VECTOR2D>& aPointList )
{
if( aPointList.size() < 2 )
return;
std::vector<VECTOR2I> polyline_corners;
for( const VECTOR2D& pt : aPointList )
polyline_corners.emplace_back( (VECTOR2I) transform( pt ) );
doDrawPolyline( polyline_corners );
}
void BASIC_GAL::DrawPolyline( const VECTOR2D aPointList[], int aListSize )
{
if( aListSize < 2 )
return;
std::vector<VECTOR2I> polyline_corners;
for( int ii = 0; ii < aListSize; ++ii )
polyline_corners.emplace_back( (VECTOR2I) transform( aPointList[ii] ) );
doDrawPolyline( polyline_corners );
}
void BASIC_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
{
VECTOR2D startVector = transform( aStartPoint );
VECTOR2D endVector = transform( aEndPoint );
if( m_DC )
{
if( m_isFillEnabled )
{
GRLine( m_isClipped ? &m_clipBox : nullptr, m_DC, startVector.x, startVector.y,
endVector.x, endVector.y, GetLineWidth(), m_Color );
}
else
{
GRCSegm( m_isClipped ? &m_clipBox : nullptr, m_DC, startVector.x, startVector.y,
endVector.x, endVector.y, GetLineWidth(), 0, m_Color );
}
}
else if( m_plotter )
{
m_plotter->MoveTo( wxPoint( startVector.x, startVector.y ) );
m_plotter->LineTo( wxPoint( endVector.x, endVector.y ) );
m_plotter->PenFinish();
}
else if( m_callback )
{
m_callback( startVector.x, startVector.y, endVector.x, endVector.y, m_callbackData );
}
}
void BASIC_GAL::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal )
{
if( aGlyph.IsStroke() )
{
const auto& strokeGlyph = static_cast<const KIFONT::STROKE_GLYPH&>( aGlyph );
for( const std::vector<VECTOR2D>& pointList : strokeGlyph )
DrawPolyline( pointList );
}
#if 0 // FONT TODO
else if( aGlyph.IsOutline() )
{
}
#endif
}

53
common/callback_gal.cpp Normal file
View File

@ -0,0 +1,53 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 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 <plotters/plotter.h>
#include <trigo.h>
#include <callback_gal.h>
using namespace KIGFX;
void CALLBACK_GAL::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal )
{
if( aGlyph.IsStroke() )
{
const KIFONT::STROKE_GLYPH& glyph = static_cast<const KIFONT::STROKE_GLYPH&>( aGlyph );
for( const std::vector<VECTOR2D>& pointList : glyph )
{
for( size_t ii = 1; ii < pointList.size(); ii++ )
m_strokeCallback( pointList[ ii - 1], pointList[ii] );
}
}
else if( aGlyph.IsOutline() )
{
const KIFONT::OUTLINE_GLYPH& glyph = static_cast<const KIFONT::OUTLINE_GLYPH&>( aGlyph );
glyph.Triangulate( m_triangleCallback );
}
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2004-2021 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2004-2022 KiCad Developers, see change_log.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
@ -30,20 +30,19 @@
#include <algorithm> // for max
#include <stddef.h> // for NULL
#include <type_traits> // for swap
#include <vector> // for vector
#include <vector>
#include <eda_item.h> // for EDA_ITEM
#include <eda_item.h>
#include <base_units.h>
#include <basic_gal.h> // for BASIC_GAL, basic_gal
#include <callback_gal.h>
#include <convert_to_biu.h> // for Mils2iu
#include <convert_basic_shapes_to_polygon.h>
#include <eda_rect.h> // for EDA_RECT
#include <eda_rect.h>
#include <eda_text.h> // for EDA_TEXT, TEXT_EFFECTS, GR_TEXT_VJUSTIF...
#include <gal/color4d.h> // for COLOR4D, COLOR4D::BLACK
#include <gr_text.h> // for GRText
#include <gr_text.h>
#include <string_utils.h> // for UnescapeString
#include <math/util.h> // for KiROUND
#include <math/vector2d.h> // for VECTOR2D
#include <math/vector2d.h>
#include <richio.h>
#include <render_settings.h>
#include <trigo.h> // for RotatePoint
@ -55,29 +54,13 @@
#include <geometry/shape_poly_set.h>
#include <wx/debug.h> // for wxASSERT
#include <wx/string.h> // wxString, wxArrayString
#include <wx/string.h>
#include <wx/gdicmn.h> // for wxPoint, wxSize
class OUTPUTFORMATTER;
class wxFindReplaceData;
void addTextSegmToPoly( int x0, int y0, int xf, int yf, void* aData )
{
TSEGM_2_POLY_PRMS* prm = static_cast<TSEGM_2_POLY_PRMS*>( aData );
TransformOvalToPolygon( *prm->m_cornerBuffer, VECTOR2I( x0, y0 ), VECTOR2I( xf, yf ),
prm->m_textWidth, prm->m_error, ERROR_INSIDE );
}
void addTextSegmToShape( int x0, int y0, int xf, int yf, void* aData )
{
TSEGM_2_SHAPE_PRMS* prm = static_cast<TSEGM_2_SHAPE_PRMS*>( aData );
prm->m_shape->AddShape( new SHAPE_SEGMENT( VECTOR2I( x0, y0 ), VECTOR2I( xf, yf ),
prm->m_penWidth ) );
}
GR_TEXT_H_ALIGN_T EDA_TEXT::MapHorizJustify( int aHorizJustify )
{
wxASSERT( aHorizJustify >= GR_TEXT_H_ALIGN_LEFT && aHorizJustify <= GR_TEXT_H_ALIGN_RIGHT );
@ -726,7 +709,7 @@ void EDA_TEXT::printOneLineOfText( const RENDER_SETTINGS* aSettings, const VECTO
if( IsMirrored() )
size.x = -size.x;
GRText( DC, aOffset + aPos, aColor, aText, GetTextAngle(), size, GetHorizJustify(),
GRPrintText( DC, aOffset + aPos, aColor, aText, GetTextAngle(), size, GetHorizJustify(),
GetVertJustify(), penWidth, IsItalic(), IsBold(), GetDrawFont() );
}
@ -844,64 +827,48 @@ std::shared_ptr<SHAPE_COMPOUND> EDA_TEXT::GetEffectiveTextShape( ) const
{
std::shared_ptr<SHAPE_COMPOUND> shape = std::make_shared<SHAPE_COMPOUND>();
KIFONT::FONT* font = GetDrawFont();
if( font->IsOutline() )
{
// Make sure the cache is up-to-date before using it
(void) GetRenderCache( m_render_cache_text );
for( std::unique_ptr<KIFONT::GLYPH>& baseGlyph : m_render_cache )
{
KIFONT::OUTLINE_GLYPH* glyph = static_cast<KIFONT::OUTLINE_GLYPH*>( baseGlyph.get() );
glyph->Triangulate(
[&]( int aPolygonIndex, const VECTOR2D& aVertex1, const VECTOR2D& aVertex2,
const VECTOR2D& aVertex3 )
{
SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
triShape->Append( aVertex1 );
triShape->Append( aVertex2 );
triShape->Append( aVertex3 );
shape->AddShape( triShape );
} );
}
}
else
{
wxSize size = GetTextSize();
int penWidth = GetEffectiveTextPenWidth();
bool forceBold = true;
TSEGM_2_SHAPE_PRMS prms;
prms.m_penWidth = penWidth;
prms.m_shape = shape.get();
if( IsMirrored() )
size.x = -size.x;
wxArrayString strings_list;
std::vector<VECTOR2I> positions;
if( IsMultilineAllowed() )
{
wxArrayString strings_list;
wxStringSplit( GetShownText(), strings_list, wxChar('\n') );
std::vector<VECTOR2I> positions;
positions.reserve( strings_list.Count() );
GetLinePositions( positions, strings_list.Count() );
for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
{
GRText( nullptr, positions[ii], COLOR4D::BLACK, strings_list.Item( ii ),
GetDrawRotation(), size, GetDrawHorizJustify(), GetDrawVertJustify(),
penWidth, IsItalic(), forceBold, font, addTextSegmToShape, &prms );
}
}
else
{
GRText( nullptr, GetDrawPos(), COLOR4D::BLACK, GetShownText(),
GetDrawRotation(), size, GetDrawHorizJustify(), GetDrawVertJustify(),
penWidth, IsItalic(), forceBold, font, addTextSegmToShape, &prms );
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,
// 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;

View File

@ -61,7 +61,9 @@ bool FONTCONFIG::FindFont( const wxString& aFontName, wxString& aFontFile )
FcResult r = FcResultNoMatch;
FcPattern* font = FcFontMatch( nullptr, pat, &r );
wxString fontName;
bool ok = false;
bool substituted = false;
if( font )
{
@ -74,22 +76,28 @@ bool FONTCONFIG::FindFont( const wxString& aFontName, wxString& aFontFile )
FcChar8* family = nullptr;
FcChar8* style = nullptr;
FcPatternGetString( font, FC_FAMILY, 0, &family );
FcPatternGetString( font, FC_STYLE, 0, &style );
if( FcPatternGetString( font, FC_FAMILY, 0, &family ) == FcResultMatch )
{
fontName = wxString::FromUTF8( (char*) family );
wxString fontName( family );
wxString styleStr( style );
if( FcPatternGetString( font, FC_STYLE, 0, &style ) == FcResultMatch )
{
wxString styleStr = wxString::FromUTF8( (char*) style );
if( !styleStr.IsEmpty() )
{
styleStr.Replace( " ", ":" );
fontName += ":" + styleStr;
}
}
// TODO: report Regular vs Book, Italic vs Oblique, etc. or filter them out?
if( aFontName.CmpNoCase( fontName ) != 0 )
wxLogWarning( _( "Font '%s' not found; substituting '%s'." ), aFontName, fontName );
if( aFontName.Contains( ":" ) )
substituted = aFontName.CmpNoCase( fontName ) != 0;
else
substituted = !fontName.StartsWith( aFontName );
}
ok = true;
}
@ -99,6 +107,8 @@ bool FONTCONFIG::FindFont( const wxString& aFontName, wxString& aFontFile )
if( !ok )
wxLogWarning( _( "Error loading font '%s'." ), aFontName );
else if( substituted )
wxLogWarning( _( "Font '%s' not found; substituting '%s'." ), aFontName, fontName );
FcPatternDestroy( pat );
return ok;

View File

@ -116,7 +116,9 @@ BOX2D OUTLINE_GLYPH::BoundingBox()
}
void OUTLINE_GLYPH::Triangulate( TRIANGULATE_CALLBACK aCallback ) const
void OUTLINE_GLYPH::Triangulate( std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2,
const VECTOR2I& aPt3 )> aCallback ) const
{
const_cast<OUTLINE_GLYPH*>( this )->CacheTriangulation();
@ -128,7 +130,7 @@ void OUTLINE_GLYPH::Triangulate( TRIANGULATE_CALLBACK aCallback ) const
{
VECTOR2I a, b, c;
polygon->GetTriangle( j, a, b, c );
aCallback( i, a, b, c );
aCallback( a, b, c );
}
}
}

View File

@ -73,9 +73,6 @@ OUTLINE_FONT* OUTLINE_FONT::LoadFont( const wxString& aFontName, bool aBold, boo
wxString fontFile;
wxString qualifiedFontName = aFontName;
if( !aBold && !aItalic )
qualifiedFontName << ":Regular";
if( aBold )
qualifiedFontName << ":Bold";

View File

@ -1765,14 +1765,15 @@ void CAIRO_GAL_BASE::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTota
{
if( aGlyph.IsStroke() )
{
const auto& strokeGlyph = static_cast<const KIFONT::STROKE_GLYPH&>( aGlyph );
const KIFONT::STROKE_GLYPH& glyph = static_cast<const KIFONT::STROKE_GLYPH&>( aGlyph );
for( const std::vector<VECTOR2D>& pointList : strokeGlyph )
for( const std::vector<VECTOR2D>& pointList : glyph )
drawPoly( pointList );
}
#if 0 // FONT TODO
else if( aGlyph.IsOutline() )
{
const KIFONT::OUTLINE_GLYPH& glyph = static_cast<const KIFONT::OUTLINE_GLYPH&>( aGlyph );
if( aNth == 0 )
{
cairo_close_path( m_currentContext );
@ -1786,46 +1787,24 @@ void CAIRO_GAL_BASE::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTota
// eventually glyphs should not be drawn as polygons at all,
// but as bitmaps with antialiasing, this is just a stopgap measure
// of getting some form of outline font display
auto triangleCallback =
[&]( int aPolygonIndex, const VECTOR2D& aVertex1, const VECTOR2D& aVertex2,
const VECTOR2D& aVertex3, void* aCallbackData )
glyph.Triangulate(
[&]( const VECTOR2D& aVertex1, const VECTOR2D& aVertex2, const VECTOR2D& aVertex3 )
{
#if 1
syncLineWidth();
const auto p0 = roundp( xform( aVertex1 ) );
const auto p1 = roundp( xform( aVertex2 ) );
const auto p2 = roundp( xform( aVertex3 ) );
const VECTOR2D p0 = roundp( xform( aVertex1 ) );
const VECTOR2D p1 = roundp( xform( aVertex2 ) );
const VECTOR2D p2 = roundp( xform( aVertex3 ) );
/*
cairo_move_to( currentContext, aVertex1.x, aVertex1.y );
cairo_line_to( currentContext, aVertex2.x, aVertex2.y );
cairo_line_to( currentContext, aVertex3.x, aVertex3.y );
cairo_line_to( currentContext, aVertex1.x, aVertex1.y );
*/
cairo_move_to( m_currentContext, p0.x, p0.y );
cairo_line_to( m_currentContext, p1.x, p1.y );
cairo_line_to( m_currentContext, p2.x, p2.y );
cairo_close_path( m_currentContext );
/*
setSourceRgba( currentContext, fillColor );
SetIsFill( true );
cairo_set_fill_rule( currentContext, CAIRO_FILL_RULE_EVEN_ODD );
cairo_set_fill_rule( m_currentContext, CAIRO_FILL_RULE_EVEN_ODD );
flushPath();
*/
//cairo_fill( currentContext );
#else
// just a silly test
/*
DrawRectangle(aVertex1, aVertex2);
DrawRectangle(aVertex2, aVertex3);
DrawRectangle(aVertex3, aVertex1);
*/
DrawTriangle( aVertex1, aVertex2, aVertex3 );
#endif
};
Triangulate( aGlyph, triangleCallback );
cairo_fill( m_currentContext );
} );
if( aNth == aTotal - 1 )
{
@ -1841,5 +1820,4 @@ void CAIRO_GAL_BASE::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTota
m_isElementAdded = true;
}
}
#endif
}

View File

@ -2428,12 +2428,11 @@ void OPENGL_GAL::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal )
m_currentManager->Color( m_fillColor );
outlineGlyph.Triangulate(
[&]( int aPolygonIndex, const VECTOR2D& aVertex1, const VECTOR2D& aVertex2,
const VECTOR2D& aVertex3 )
[&]( const VECTOR2D& aPt1, const VECTOR2D& aPt2, const VECTOR2D& aPt3 )
{
m_currentManager->Vertex( aVertex1.x, aVertex1.y, m_layerDepth );
m_currentManager->Vertex( aVertex2.x, aVertex2.y, m_layerDepth );
m_currentManager->Vertex( aVertex3.x, aVertex3.y, m_layerDepth );
m_currentManager->Vertex( aPt1.x, aPt1.y, m_layerDepth );
m_currentManager->Vertex( aPt2.x, aPt2.y, m_layerDepth );
m_currentManager->Vertex( aPt3.x, aPt3.y, m_layerDepth );
} );
}
}

View File

@ -120,7 +120,7 @@ void GRSetColorPen( wxDC* DC, const COLOR4D& Color, int width, wxPenStyle style
// Under OSX and while printing when wxPen is set to 0, renderer follows the request drawing
// nothing & in the bitmap world the minimum is enough to light a pixel, in vectorial one not
if( width <= 1 )
if( width <= 1 && DC->GetBrush().GetStyle() != wxBRUSHSTYLE_SOLID )
width = DC->DeviceToLogicalXRel( 1 );
if( s_ForceBlackPen )

View File

@ -4,7 +4,7 @@
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2022 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
@ -30,7 +30,7 @@
#include <math/util.h> // for KiROUND
#include <font/font.h>
#include <basic_gal.h>
#include <callback_gal.h>
/**
@ -107,9 +107,9 @@ int GraphicTextWidth( const wxString& aText, KIFONT::FONT* aFont, const VECTOR2I
/**
* Draw a graphic text (like footprint texts).
* Print a graphic text through wxDC.
*
* @param aDC is the current Device Context. NULL if draw within a 3D GL Canvas.
* @param aDC is the current Device Context.
* @param aPos is the text position (according to h_justify, v_justify).
* @param aColor is the text color.
* @param aText is the text to draw.
@ -123,19 +123,11 @@ int GraphicTextWidth( const wxString& aText, KIFONT::FONT* aFont, const VECTOR2I
* @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 aCallback( int x0, int y0, int xf, int yf, void* aData ) is a function called
* (if non null) to draw each segment. used to draw 3D texts or for plotting.
* NULL for normal drawings
* @param aCallbackData is the auxiliary parameter aData for the callback function.
* can be nullptr if no auxiliary parameter is needed
* @param aPlotter is a PLOTTER instance, when this function is used to plot
* the text. NULL to draw this text.
*/
void GRText( wxDC* aDC, const VECTOR2I& aPos, const COLOR4D& aColor, 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, void (* aCallback)( int x0, int y0, int xf, int yf, void* aData ),
void* aCallbackData, PLOTTER* aPlotter )
void GRPrintText( wxDC* aDC, const VECTOR2I& aPos, const COLOR4D& aColor, 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 )
{
bool fill_mode = true;
@ -151,13 +143,63 @@ void GRText( wxDC* aDC, const VECTOR2I& aPos, const COLOR4D& aColor, const wxStr
fill_mode = false;
}
basic_gal.SetIsFill( fill_mode );
basic_gal.SetLineWidth( aWidth );
basic_gal.SetPlotter( aPlotter );
basic_gal.SetCallback( aCallback, aCallbackData );
basic_gal.m_DC = aDC;
basic_gal.m_Color = aColor;
basic_gal.SetClipBox( nullptr );
GRText( aPos, aText, aOrient, aSize, aH_justify, aV_justify, aWidth, aItalic, aBold, aFont,
// Stroke callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{
if( fill_mode )
GRLine( nullptr, aDC, aPt1.x, aPt1.y, aPt2.x, aPt2.y, aWidth, aColor );
else
GRCSegm( nullptr, aDC, aPt1.x, aPt1.y, aPt2.x, aPt2.y, aWidth, 0, aColor );
},
// Triangulation callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
{
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;
@ -175,7 +217,7 @@ void GRText( wxDC* aDC, const VECTOR2I& aPos, const COLOR4D& aColor, const wxStr
attributes.m_Size = size;
aFont->Draw( &basic_gal, aText, VECTOR2D( aPos ), attributes );
aFont->Draw( &callback_gal, aText, VECTOR2D( aPos ), attributes );
}

View File

@ -647,7 +647,7 @@ void PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_T aFill, int a
* @param aV_justify is the vertical justification (bottom, center, top).
* @param aPenWidth is the line width (if = 0, use plot default line width).
* @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 aBold use true to use a bold font Useful only with default width value (aPenWidth = 0).
* @param aMultilineAllowed use true to plot text as multiline, otherwise single line.
* @param aData is a parameter used by some plotters in SetCurrentLineWidth(),
* not directly used here.
@ -669,6 +669,29 @@ void PLOTTER::Text( const VECTOR2I& aPos,
SetColor( aColor );
SetCurrentLineWidth( aPenWidth, aData );
GRText( nullptr, aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, aPenWidth,
aItalic, aBold, aFont, nullptr, nullptr, this );
if( aPenWidth == 0 && aBold ) // Use default values if aPenWidth == 0
aPenWidth = GetPenSizeForBold( std::min( aSize.x, aSize.y ) );
if( aPenWidth < 0 )
aPenWidth = -aPenWidth;
GRText( aPos, aText, aOrient, aSize, aH_justify, aV_justify, aPenWidth, aItalic, aBold, aFont,
// Stroke callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{
MoveTo( (wxPoint) aPt1 );
LineTo( (wxPoint) aPt2 );
PenFinish();
},
// Triangulation callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
{
std::vector<VECTOR2I> cornerList;
cornerList.reserve( 3 );
for( const VECTOR2I& pt : { aPt1, aPt2, aPt3, aPt1 } )
cornerList.emplace_back( pt );
PlotPoly( cornerList, FILL_T::FILLED_SHAPE, 0, aData );
} );
}

View File

@ -131,7 +131,7 @@ void LIB_FIELD::print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset
VECTOR2I text_pos = aTransform.TransformCoordinate( GetTextPos() ) + aOffset;
wxString text = aData ? *static_cast<wxString*>( aData ) : GetText();
GRText( DC, text_pos, color, text, GetTextAngle(), GetTextSize(), GetHorizJustify(),
GRPrintText( DC, text_pos, color, text, GetTextAngle(), GetTextSize(), GetHorizJustify(),
GetVertJustify(), penWidth, IsItalic(), IsBold(), GetDrawFont() );
}

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2022 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
@ -32,7 +32,6 @@
#include <symbol_editor/symbol_editor_settings.h>
#include <trigo.h>
#include <string_utils.h>
#include <basic_gal.h>
#include "sch_painter.h"
// small margin in internal units between the pin text and the pin line
@ -403,23 +402,23 @@ void LIB_PIN::printPinTexts( const RENDER_SETTINGS* aSettings, VECTOR2I& aPinPos
if( aPinOrient == PIN_RIGHT )
{
x = x1 + aTextInside;
GRText( DC, VECTOR2I( x, y1 ), NameColor, name, EDA_ANGLE::HORIZONTAL,
pinNameSize, GR_TEXT_H_ALIGN_LEFT, GR_TEXT_V_ALIGN_CENTER, namePenWidth,
false, false, font );
GRPrintText( DC, VECTOR2I( x, y1 ), NameColor, name, EDA_ANGLE::HORIZONTAL,
pinNameSize, GR_TEXT_H_ALIGN_LEFT, GR_TEXT_V_ALIGN_CENTER,
namePenWidth, false, false, font );
}
else // Orient == PIN_LEFT
{
x = x1 - aTextInside;
GRText( DC, VECTOR2I( x, y1 ), NameColor, name, EDA_ANGLE::HORIZONTAL,
pinNameSize, GR_TEXT_H_ALIGN_RIGHT, GR_TEXT_V_ALIGN_CENTER, namePenWidth,
false, false, font );
GRPrintText( DC, VECTOR2I( x, y1 ), NameColor, name, EDA_ANGLE::HORIZONTAL,
pinNameSize, GR_TEXT_H_ALIGN_RIGHT, GR_TEXT_V_ALIGN_CENTER,
namePenWidth, false, false, font );
}
}
if( aDrawPinNum )
{
GRText( DC, VECTOR2I(( x1 + aPinPos.x) / 2, y1 - num_offset ), NumColor, number,
EDA_ANGLE::HORIZONTAL, pinNumSize, GR_TEXT_H_ALIGN_CENTER,
GRPrintText( DC, VECTOR2I(( x1 + aPinPos.x) / 2, y1 - num_offset ), NumColor,
number, EDA_ANGLE::HORIZONTAL, pinNumSize, GR_TEXT_H_ALIGN_CENTER,
GR_TEXT_V_ALIGN_BOTTOM, numPenWidth, false, false, font );
}
}
@ -432,14 +431,14 @@ void LIB_PIN::printPinTexts( const RENDER_SETTINGS* aSettings, VECTOR2I& aPinPos
if( aDrawPinName )
{
GRText( DC, VECTOR2I( x1, y ), NameColor, name, EDA_ANGLE::VERTICAL, pinNameSize,
GR_TEXT_H_ALIGN_RIGHT, GR_TEXT_V_ALIGN_CENTER, namePenWidth, false,
false, font );
GRPrintText( DC, VECTOR2I( x1, y ), NameColor, name, EDA_ANGLE::VERTICAL,
pinNameSize, GR_TEXT_H_ALIGN_RIGHT, GR_TEXT_V_ALIGN_CENTER,
namePenWidth, false, false, font );
}
if( aDrawPinNum )
{
GRText( DC, VECTOR2I( x1 - num_offset, ( y1 + aPinPos.y) / 2 ), NumColor,
GRPrintText( DC, VECTOR2I( x1 - num_offset, ( y1 + aPinPos.y) / 2 ), NumColor,
number, EDA_ANGLE::VERTICAL, pinNumSize, GR_TEXT_H_ALIGN_CENTER,
GR_TEXT_V_ALIGN_BOTTOM, numPenWidth, false, false, font );
}
@ -450,14 +449,14 @@ void LIB_PIN::printPinTexts( const RENDER_SETTINGS* aSettings, VECTOR2I& aPinPos
if( aDrawPinName )
{
GRText( DC, VECTOR2I( x1, y ), NameColor, name, EDA_ANGLE::VERTICAL, pinNameSize,
GR_TEXT_H_ALIGN_LEFT, GR_TEXT_V_ALIGN_CENTER, namePenWidth, false,
false, font );
GRPrintText( DC, VECTOR2I( x1, y ), NameColor, name, EDA_ANGLE::VERTICAL,
pinNameSize, GR_TEXT_H_ALIGN_LEFT, GR_TEXT_V_ALIGN_CENTER,
namePenWidth, false, false, font );
}
if( aDrawPinNum )
{
GRText( DC, VECTOR2I( x1 - num_offset, ( y1 + aPinPos.y) / 2 ), NumColor,
GRPrintText( DC, VECTOR2I( x1 - num_offset, ( y1 + aPinPos.y) / 2 ), NumColor,
number, EDA_ANGLE::VERTICAL, pinNumSize, GR_TEXT_H_ALIGN_CENTER,
GR_TEXT_V_ALIGN_BOTTOM, numPenWidth, false, false, font );
}
@ -472,16 +471,16 @@ void LIB_PIN::printPinTexts( const RENDER_SETTINGS* aSettings, VECTOR2I& aPinPos
if( aDrawPinName )
{
x = ( x1 + aPinPos.x) / 2;
GRText( DC, VECTOR2I( x, y1 - name_offset ), NameColor, name, EDA_ANGLE::HORIZONTAL,
pinNameSize, GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_BOTTOM,
namePenWidth, false, false, font );
GRPrintText( DC, VECTOR2I( x, y1 - name_offset ), NameColor, name,
EDA_ANGLE::HORIZONTAL, pinNameSize, GR_TEXT_H_ALIGN_CENTER,
GR_TEXT_V_ALIGN_BOTTOM, namePenWidth, false, false, font );
}
if( aDrawPinNum )
{
x = ( x1 + aPinPos.x) / 2;
GRText( DC, VECTOR2I( x, y1 + num_offset ), NumColor, number, EDA_ANGLE::HORIZONTAL,
pinNumSize, GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_TOP, numPenWidth,
false, false, font );
GRPrintText( DC, VECTOR2I( x, y1 + num_offset ), NumColor, number,
EDA_ANGLE::HORIZONTAL, pinNumSize, GR_TEXT_H_ALIGN_CENTER,
GR_TEXT_V_ALIGN_TOP, numPenWidth, false, false, font );
}
}
else /* Its a vertical line. */
@ -489,16 +488,16 @@ void LIB_PIN::printPinTexts( const RENDER_SETTINGS* aSettings, VECTOR2I& aPinPos
if( aDrawPinName )
{
y = ( y1 + aPinPos.y) / 2;
GRText( DC, VECTOR2I( x1 - name_offset, y ), NameColor, name, EDA_ANGLE::VERTICAL,
pinNameSize, GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_BOTTOM,
namePenWidth, false, false, font );
GRPrintText( DC, VECTOR2I( x1 - name_offset, y ), NameColor, name,
EDA_ANGLE::VERTICAL, pinNameSize, GR_TEXT_H_ALIGN_CENTER,
GR_TEXT_V_ALIGN_BOTTOM, namePenWidth, false, false, font );
}
if( aDrawPinNum )
{
GRText( DC, VECTOR2I( x1 + num_offset, ( y1 + aPinPos.y) / 2 ), NumColor, number,
EDA_ANGLE::VERTICAL, pinNumSize, GR_TEXT_H_ALIGN_CENTER, GR_TEXT_V_ALIGN_TOP,
numPenWidth, false, false, font );
GRPrintText( DC, VECTOR2I( x1 + num_offset, ( y1 + aPinPos.y) / 2 ), NumColor,
number, EDA_ANGLE::VERTICAL, pinNumSize, GR_TEXT_H_ALIGN_CENTER,
GR_TEXT_V_ALIGN_TOP, numPenWidth, false, false, font );
}
}
}
@ -554,7 +553,7 @@ void LIB_PIN::printPinElectricalTypeName( const RENDER_SETTINGS* aSettings, VECT
break;
}
GRText( DC, txtpos, color, typeName, orient, wxSize( textSize, textSize ), hjustify,
GRPrintText( DC, txtpos, color, typeName, orient, wxSize( textSize, textSize ), hjustify,
GR_TEXT_V_ALIGN_CENTER, pensize, false, false, GetDrawFont() );
}

View File

@ -345,7 +345,7 @@ void LIB_TEXT::print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset,
// Calculate pos according to mirror/rotation.
txtpos = aTransform.TransformCoordinate( txtpos ) + aOffset;
GRText( DC, txtpos, color, GetShownText(), orient, GetTextSize(), GR_TEXT_H_ALIGN_CENTER,
GRPrintText( DC, txtpos, color, GetShownText(), orient, GetTextSize(), GR_TEXT_H_ALIGN_CENTER,
GR_TEXT_V_ALIGN_CENTER, penWidth, IsItalic(), IsBold(), GetDrawFont() );
}

View File

@ -357,7 +357,7 @@ void SCH_FIELD::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset
*/
textpos = GetBoundingBox().Centre() + aOffset;
GRText( DC, textpos, color, GetShownText(), orient, GetTextSize(), GR_TEXT_H_ALIGN_CENTER,
GRPrintText( DC, textpos, color, GetShownText(), orient, GetTextSize(), GR_TEXT_H_ALIGN_CENTER,
GR_TEXT_V_ALIGN_CENTER, penWidth, IsItalic(), IsBold(), GetDrawFont() );
}

View File

@ -1,181 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2020 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
*/
#ifndef BASIC_GAL_H
#define BASIC_GAL_H
#include <eda_rect.h>
#include <gal/graphics_abstraction_layer.h>
class PLOTTER;
/*
* A minimal GAL implementation to draw, plot and convert stroke texts to a set of segments
* for DRC tests, and to calculate text sizes.
*
* Currently it allows one to use GAL and STROKE_FONT methods in legacy draw mode
* (using wxDC functions) in plot functions only for texts.
* It is used also to calculate the text bounding boxes
*
* The main purpose is to avoid duplicate code to do the same thing in GAL canvas,
* print & plotter canvasses and DRC.
*
* It will be certainly removed when a full GAL canvas using wxDC is implemented
* (or at least restricted to plotter and DRC "canvas")
*/
struct TRANSFORM_PRM // A helper class to transform coordinates in BASIC_GAL canvas
{
VECTOR2D m_rotCenter;
VECTOR2D m_moveOffset;
double m_rotAngle;
};
class BASIC_GAL: public KIGFX::GAL
{
public:
BASIC_GAL( KIGFX::GAL_DISPLAY_OPTIONS& aDisplayOptions ) :
GAL( aDisplayOptions ),
m_callback( nullptr ),
m_DC( nullptr ),
m_Color( RED ),
m_transform(),
m_clipBox(),
m_isClipped( false ),
m_callbackData( nullptr ),
m_plotter( nullptr )
{
}
void SetPlotter( PLOTTER* aPlotter )
{
m_plotter = aPlotter;
}
void SetCallback( void (* aCallback)( int x0, int y0, int xf, int yf, void* aData ),
void* aData )
{
m_callback = aCallback;
m_callbackData = aData;
}
/// Set a clip box for drawings
/// If NULL, no clip will be made
void SetClipBox( EDA_RECT* aClipBox )
{
m_isClipped = aClipBox != nullptr;
if( aClipBox )
m_clipBox = *aClipBox;
}
/// Save the context.
void Save() override
{
m_transformHistory.push( m_transform );
}
void Restore() override
{
m_transform = m_transformHistory.top();
m_transformHistory.pop();
}
/**
* Draw a polyline
*
* @param aPointList is a list of 2D-Vectors containing the polyline points.
*/
void DrawPolyline( const std::deque<VECTOR2D>& aPointList ) override;
void DrawPolyline( const std::vector<VECTOR2D>& aPointList ) override;
void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) override;
/**
* Start and end points are defined as 2D-Vectors.
*
* @param aStartPoint is the start point of the line.
* @param aEndPoint is the end point of the line.
*/
void DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) override;
/**
* Draw a polygon representing an outline font glyph.
*/
void DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal ) override;
/**
* Translate the context.
*
* @param aTranslation is the translation vector.
*/
void Translate( const VECTOR2D& aTranslation ) override
{
m_transform.m_moveOffset += aTranslation;
}
/**
* Rotate the context.
*
* @param aAngle is the rotation angle in radians.
*/
void Rotate( double aAngle ) override
{
m_transform.m_rotAngle = aAngle;
m_transform.m_rotCenter = m_transform.m_moveOffset;
}
private:
void doDrawPolyline( const std::vector<VECTOR2I>& aLocalPointList );
// Apply the rotation/translation transform to aPoint
const VECTOR2D transform( const VECTOR2D& aPoint ) const;
// When calling the draw functions outside a wxDC, to get the basic drawings lines /
// polylines ..., a callback function (used in DRC) to store coordinates of each segment:
void (* m_callback)( int x0, int y0, int xf, int yf, void* aData );
public:
wxDC* m_DC;
KIGFX::COLOR4D m_Color;
private:
TRANSFORM_PRM m_transform;
std::stack<TRANSFORM_PRM> m_transformHistory;
// A clip box, to clip drawings in a wxDC (mandatory to avoid draw issues)
EDA_RECT m_clipBox; // The clip box
bool m_isClipped; // Allows/disallows clipping
void* m_callbackData; // a optional parameter for m_callback
PLOTTER* m_plotter; // When calling the draw functions for plot, the
// plotter acts as a wxDC to plot basic items.
};
extern BASIC_GAL basic_gal;
#endif // define BASIC_GAL_H

60
include/callback_gal.h Normal file
View File

@ -0,0 +1,60 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 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
*/
#ifndef CALLBACK_GAL_H
#define CALLBACK_GAL_H
#include <gal/graphics_abstraction_layer.h>
class CALLBACK_GAL: public KIGFX::GAL
{
public:
CALLBACK_GAL( KIGFX::GAL_DISPLAY_OPTIONS& aDisplayOptions,
std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2 )> aStrokeCallback,
std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2,
const VECTOR2I& aPt3 )> aTriangleCallback ) :
GAL( aDisplayOptions )
{
m_strokeCallback = aStrokeCallback;
m_triangleCallback = aTriangleCallback;
}
/**
* Draw a polygon representing an outline font glyph.
*/
void DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal ) override;
private:
std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2 )> m_strokeCallback;
std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2,
const VECTOR2I& aPt3 )> m_triangleCallback;
};
#endif // define CALLBACK_GAL_H

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2004-2022 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
@ -39,33 +39,6 @@ class SHAPE_POLY_SET;
class wxFindReplaceData;
/**
* A helper for the text to polygon callback function.
*
* These variables are parameters used in #addTextSegmToPoly but #addTextSegmToPoly is a
* callback function so the cannot be sent as arguments.
*/
struct TSEGM_2_POLY_PRMS
{
int m_textWidth;
int m_error;
SHAPE_POLY_SET* m_cornerBuffer;
};
struct TSEGM_2_SHAPE_PRMS
{
int m_penWidth;
SHAPE_COMPOUND* m_shape;
};
/**
* Callback function used to convert text segments to polygons.
*/
extern void addTextSegmToPoly( int x0, int y0, int xf, int yf, void* aData );
namespace KIGFX
{
class RENDER_SETTINGS;

View File

@ -31,9 +31,6 @@
#include <geometry/shape_poly_set.h>
#include <wx/debug.h>
typedef std::function<void( int, const VECTOR2I& aPoint1, const VECTOR2I& aPoint2,
const VECTOR2I& aPoint3 )>
TRIANGULATE_CALLBACK;
namespace KIFONT
{
@ -69,7 +66,9 @@ public:
BOX2D BoundingBox() override;
void Triangulate( TRIANGULATE_CALLBACK aCallback ) const;
void Triangulate( std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2,
const VECTOR2I& aPt3 )> aCallback ) const;
};

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2009-2014 Jerry Jacobs
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2022 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
@ -88,37 +88,54 @@ int GraphicTextWidth( const wxString& aText, KIFONT::FONT* aFont, const VECTOR2I
int aThickness, bool aBold, bool aItalic );
/**
* Draw a graphic text (like footprint text)
* Print a graphic text through wxDC.
*
* @param aClipBox the clipping rect, or NULL if no clipping.
* @param aDC the current Device Context. NULL if draw within a 3D GL Canvas.
* @param aPos text position (according to h_justify, v_justify).
* @param aColor (COLOR4D) = text color.
* @param aText text to draw.
* @param aOrient angle.
* @param aSize text size (size.x or size.y can be < 0 for mirrored texts).
* @param aH_justify horizontal justification (Left, center, right).
* @param aV_justify vertical justification (bottom, center, top).
* @param aWidth line width (pen width) (default = 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 true to simulate an italic font.
* @param aBold true to use a bold font.
* @param aDC is the current Device Context.
* @param aPos is the text position (according to h_justify, v_justify).
* @param aColor is the text color.
* @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 aCallback ( int x0, int y0, int xf, int yf, void* aData ) is a function called
* (if non null) to draw each segment. used to draw 3D texts or for plotting.
* NULL for normal drawings.
* @param aCallbackData is the auxiliary parameter aData for the callback function.
* This can be nullptr if no auxiliary parameter is needed.
* @param aPlotter = a pointer to a PLOTTER instance, when this function is used to plot
* the text. NULL to draw this text.
*/
void GRText( wxDC* aDC, const VECTOR2I& aPos, const KIGFX::COLOR4D& aColor, const wxString& aText,
const EDA_ANGLE& aOrient, const VECTOR2I& aSize, enum GR_TEXT_H_ALIGN_T aH_justify,
void GRPrintText( wxDC* aDC, const VECTOR2I& aPos, const KIGFX::COLOR4D& aColor,
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 );
/**
* 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,
void (*aCallback)( int x0, int y0, int xf, int yf, void* aData ) = nullptr,
void* aCallbackData = nullptr, PLOTTER* aPlotter = nullptr );
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

@ -406,7 +406,7 @@ public:
const VECTOR2I& aSize,
enum GR_TEXT_H_ALIGN_T aH_justify,
enum GR_TEXT_V_ALIGN_T aV_justify,
int aWidth,
int aPenWidth,
bool aItalic,
bool aBold,
bool aMultilineAllowed = false,

View File

@ -222,7 +222,7 @@ DIALOG_TEXT_PROPERTIES_BASE::DIALOG_TEXT_PROPERTIES_BASE( wxWindow* parent, wxWi
m_PositionYUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_PositionYUnits->Wrap( -1 );
gbSizer1->Add( m_PositionYUnits, wxGBPosition( 5, 6 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
gbSizer1->Add( m_PositionYUnits, wxGBPosition( 4, 6 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
m_OrientLabel = new wxStaticText( this, wxID_ANY, _("Orientation:"), wxDefaultPosition, wxDefaultSize, 0 );
m_OrientLabel->Wrap( -1 );
@ -235,7 +235,7 @@ DIALOG_TEXT_PROPERTIES_BASE::DIALOG_TEXT_PROPERTIES_BASE( wxWindow* parent, wxWi
m_OrientCtrl->Append( _("90.0") );
m_OrientCtrl->Append( _("-90.0") );
m_OrientCtrl->Append( _("180.0") );
gbSizer1->Add( m_OrientCtrl, wxGBPosition( 5, 5 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
gbSizer1->Add( m_OrientCtrl, wxGBPosition( 5, 5 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 );
bMainSizer->Add( gbSizer1, 0, wxEXPAND|wxRIGHT|wxLEFT, 10 );

View File

@ -2483,7 +2483,7 @@
<property name="colspan">1</property>
<property name="column">6</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="row">5</property>
<property name="row">4</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
@ -2610,7 +2610,7 @@
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxEXPAND</property>
<property name="row">5</property>
<property name="rowspan">1</property>
<object class="wxComboBox" expanded="0">

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2022 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
@ -35,6 +35,7 @@
#include <string_utils.h>
#include <painter.h>
#include <geometry/shape_compound.h>
#include <convert_basic_shapes_to_polygon.h>
FP_TEXT::FP_TEXT( FOOTPRINT* aParentFootprint, TEXT_TYPE text_type ) :
BOARD_ITEM( aParentFootprint, PCB_FP_TEXT_T ),
@ -464,20 +465,28 @@ void FP_TEXT::TransformTextShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerB
PCB_LAYER_ID aLayer, int aClearance,
int aError, ERROR_LOC aErrorLoc ) const
{
struct TSEGM_2_POLY_PRMS prms;
prms.m_cornerBuffer = &aCornerBuffer;
prms.m_textWidth = GetEffectiveTextPenWidth() + ( 2 * aClearance );
prms.m_error = aError;
wxSize size = GetTextSize();
int penWidth = GetEffectiveTextPenWidth();
if( IsMirrored() )
size.x = -size.x;
GRText( nullptr, GetTextPos(), BLACK, GetShownText(), GetDrawRotation(), size,
GetHorizJustify(), GetVertJustify(), penWidth, IsItalic(), IsBold(), GetDrawFont(),
addTextSegmToPoly, &prms );
GRText( GetTextPos(), GetShownText(), GetDrawRotation(), size, GetHorizJustify(),
GetVertJustify(), penWidth, IsItalic(), IsBold(), GetDrawFont(),
// Stroke callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{
TransformOvalToPolygon( aCornerBuffer, aPt1, aPt2, penWidth+ ( 2 * aClearance ),
aError, ERROR_INSIDE );
},
// Triangulation callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
{
aCornerBuffer.NewOutline();
for( const VECTOR2I& point : { aPt1, aPt2, aPt3 } )
aCornerBuffer.Append( point.x, point.y );
} );
}

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2022 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
@ -36,6 +36,7 @@
#include <trigo.h>
#include <string_utils.h>
#include <geometry/shape_compound.h>
#include <convert_basic_shapes_to_polygon.h>
using KIGFX::PCB_RENDER_SETTINGS;
@ -226,11 +227,9 @@ std::shared_ptr<SHAPE> PCB_TEXT::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
void PCB_TEXT::TransformTextShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
PCB_LAYER_ID aLayer, int aClearanceValue,
PCB_LAYER_ID aLayer, int aClearance,
int aError, ERROR_LOC aErrorLoc ) const
{
struct TSEGM_2_POLY_PRMS prms;
wxSize size = GetTextSize();
if( IsMirrored() )
@ -238,13 +237,22 @@ void PCB_TEXT::TransformTextShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCorner
int penWidth = GetEffectiveTextPenWidth();
prms.m_cornerBuffer = &aCornerBuffer;
prms.m_textWidth = GetEffectiveTextPenWidth() + ( 2 * aClearanceValue );
prms.m_error = aError;
GRText( GetTextPos(), GetShownText(), GetTextAngle(), size, GetHorizJustify(),
GetVertJustify(), penWidth, IsItalic(), IsBold(), GetDrawFont(),
// Stroke callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{
TransformOvalToPolygon( aCornerBuffer, aPt1, aPt2, penWidth+ ( 2 * aClearance ),
aError, ERROR_INSIDE );
},
// Triangulation callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
{
aCornerBuffer.NewOutline();
GRText( nullptr, GetTextPos(), COLOR4D::BLACK, GetShownText(), GetTextAngle(), size,
GetHorizJustify(), GetVertJustify(), penWidth, IsItalic(), IsBold(), GetDrawFont(),
addTextSegmToPoly, &prms );
for( const VECTOR2I& point : { aPt1, aPt2, aPt3 } )
aCornerBuffer.Append( point.x, point.y );
} );
}