KiCad PCB EDA Suite
Loading...
Searching...
No Matches
drc_test_provider_text_dims.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <macros.h>
25#include <pcb_field.h>
26#include <pcb_text.h>
27#include <pcb_textbox.h>
28#include <drc/drc_engine.h>
29#include <drc/drc_item.h>
30#include <drc/drc_rule.h>
32#include <font/font.h>
33#include <pcb_dimension.h>
34
35
36/*
37 Text dimensions tests.
38 Errors generated:
39 - DRCE_TEXT_HEIGHT
40 - DRCE_TEXT_THICKNESS
41*/
42
44{
45public:
47 {}
48
49 virtual ~DRC_TEST_PROVIDER_TEXT_DIMS() = default;
50
51 virtual bool Run() override;
52
53 virtual const wxString GetName() const override { return wxT( "text_dimensions" ); };
54};
55
56
58{
59 const int progressDelta = 250;
60 int count = 0;
61 int ii = 0;
62
65 {
66 REPORT_AUX( wxT( "Text dimension violations ignored. Tests not run." ) );
67 return true; // continue with other tests
68 }
69
72 {
73 REPORT_AUX( wxT( "No text height or text thickness constraints found. Tests not run." ) );
74 return true; // continue with other tests
75 }
76
77 if( !reportPhase( _( "Checking text dimensions..." ) ) )
78 return false; // DRC cancelled
79
80 auto checkTextHeight =
81 [&]( BOARD_ITEM* item, EDA_TEXT* text ) -> bool
82 {
84 return false;
85
87 nullptr, item->GetLayer() );
88
89 if( constraint.GetSeverity() == RPT_SEVERITY_IGNORE )
90 return true;
91
92 int actualHeight = text->GetTextSize().y;
93
94 if( constraint.Value().HasMin() && actualHeight < constraint.Value().Min() )
95 {
96 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_TEXT_HEIGHT );
97 wxString msg = formatMsg( _( "(%s min height %s; actual %s)" ),
98 constraint.GetName(),
99 constraint.Value().Min(),
100 actualHeight );
101
102 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
103 drcItem->SetItems( item );
104 drcItem->SetViolatingRule( constraint.GetParentRule() );
105
106 reportViolation( drcItem, item->GetPosition(), item->GetLayer() );
107 }
108
109 if( constraint.Value().HasMax() && actualHeight > constraint.Value().Max() )
110 {
111 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_TEXT_HEIGHT );
112 wxString msg = formatMsg( _( "(%s max height %s; actual %s)" ),
113 constraint.GetName(),
114 constraint.Value().Max(),
115 actualHeight );
116
117 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
118 drcItem->SetItems( item );
119 drcItem->SetViolatingRule( constraint.GetParentRule() );
120
121 reportViolation( drcItem, item->GetPosition(), item->GetLayer() );
122 }
123
124 return true;
125 };
126
127 auto checkTextThickness =
128 [&]( BOARD_ITEM* item, EDA_TEXT* text ) -> bool
129 {
131 nullptr, item->GetLayer() );
132
133 if( constraint.GetSeverity() == RPT_SEVERITY_IGNORE )
134 return true;
135
136 KIFONT::FONT* font = text->GetFont();
137
138 if( !font )
139 font = KIFONT::FONT::GetFont( wxEmptyString, text->IsBold(), text->IsItalic() );
140
141 if( font->IsOutline() )
142 {
143 if( !constraint.Value().HasMin() || constraint.Value().Min() <= 0 )
144 return true;
145
146 auto* glyphs = text->GetRenderCache( font, text->GetShownText( true ) );
147 bool collapsedStroke = false;
148 bool collapsedArea = false;
149
150 for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *glyphs )
151 {
152 // Ensure the glyph is a OUTLINE_GLYPH (for instance, overbars in outline
153 // font text are represented as STROKE_GLYPHs).
154 if( !glyph->IsOutline() )
155 continue;
156
157 auto outlineGlyph = static_cast<KIFONT::OUTLINE_GLYPH*>( glyph.get() );
158 int outlineCount = outlineGlyph->OutlineCount();
159 int holeCount = 0;
160
161 if( outlineCount == 0 )
162 continue; // ignore spaces
163
164 for( ii = 0; ii < outlineCount; ++ii )
165 holeCount += outlineGlyph->HoleCount( ii );
166
167 SHAPE_POLY_SET poly = outlineGlyph->CloneDropTriangulation();
168 poly.Deflate( constraint.Value().Min() / 2,
169 CORNER_STRATEGY::CHAMFER_ALL_CORNERS, ARC_LOW_DEF );
170 poly.Simplify();
171
172 int resultingOutlineCount = poly.OutlineCount();
173 int resultingHoleCount = 0;
174
175 for( ii = 0; ii < resultingOutlineCount; ++ii )
176 resultingHoleCount += poly.HoleCount( ii );
177
178 if( ( resultingOutlineCount != outlineCount )
179 || ( resultingHoleCount != holeCount ) )
180 {
181 collapsedStroke = true;
182 break;
183 }
184
185 double glyphArea = outlineGlyph->Area();
186
187 if( glyphArea == 0 )
188 continue;
189
190 poly.Inflate( constraint.Value().Min() / 2,
191 CORNER_STRATEGY::CHAMFER_ALL_CORNERS, ARC_LOW_DEF, true );
192
193 double resultingGlyphArea = poly.Area();
194
195 if( ( std::abs( resultingGlyphArea - glyphArea ) / glyphArea ) > 0.1 )
196 {
197 collapsedArea = true;
198 break;
199 }
200 }
201
202 if( collapsedStroke || collapsedArea )
203 {
204 auto drcItem = DRC_ITEM::Create( DRCE_TEXT_THICKNESS );
205 wxString msg;
206
207 msg = _( "(TrueType font characters with insufficient stroke weight)" );
208
209 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
210 drcItem->SetItems( item );
211 drcItem->SetViolatingRule( constraint.GetParentRule() );
212
213 reportViolation( drcItem, item->GetPosition(), item->GetLayer() );
214 }
215 }
216 else
217 {
218 int actualThickness = text->GetEffectiveTextPenWidth();
219
220 if( constraint.Value().HasMin() && actualThickness < constraint.Value().Min() )
221 {
222 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_TEXT_THICKNESS );
223 wxString msg = formatMsg( _( "(%s min thickness %s; actual %s)" ),
224 constraint.GetName(),
225 constraint.Value().Min(),
226 actualThickness );
227
228 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
229 drcItem->SetItems( item );
230 drcItem->SetViolatingRule( constraint.GetParentRule() );
231
232 reportViolation( drcItem, item->GetPosition(), item->GetLayer() );
233 }
234
235 if( constraint.Value().HasMax() && actualThickness > constraint.Value().Max() )
236 {
237 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_TEXT_THICKNESS );
238 wxString msg = formatMsg( _( "(%s max thickness %s; actual %s)" ),
239 constraint.GetName(),
240 constraint.Value().Max(),
241 actualThickness );
242
243 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
244 drcItem->SetItems( item );
245 drcItem->SetViolatingRule( constraint.GetParentRule() );
246
247 reportViolation( drcItem, item->GetPosition(), item->GetLayer() );
248 }
249 }
250
251 return true;
252 };
253
254 static const std::vector<KICAD_T> itemTypes = {
258 };
259
261 [&]( BOARD_ITEM* item ) -> bool
262 {
263 ++count;
264 return true;
265 } );
266
268 [&]( BOARD_ITEM* item ) -> bool
269 {
270 if( !reportProgress( ii++, count, progressDelta ) )
271 return false;
272
273 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item ) )
274 {
275 int strikes = 0;
276
277 if( !text->IsVisible() )
278 return true;
279
281 strikes++;
282 else
283 checkTextThickness( item, text );
284
286 strikes++;
287 else
288 checkTextHeight( item, text );
289
290 if( strikes >= 2 )
291 return false;
292 }
293
294 return true;
295 } );
296
297 return !m_drcEngine->IsCancelled();
298}
299
300
301namespace detail
302{
304}
constexpr int ARC_LOW_DEF
Definition: base_units.h:128
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:232
wxString GetName() const
Definition: drc_rule.h:168
SEVERITY GetSeverity() const
Definition: drc_rule.h:181
MINOPTMAX< int > & Value()
Definition: drc_rule.h:161
DRC_RULE * GetParentRule() const
Definition: drc_rule.h:164
bool HasRulesForConstraintType(DRC_CONSTRAINT_T constraintID)
bool IsErrorLimitExceeded(int error_code)
DRC_CONSTRAINT EvalRules(DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
Definition: drc_engine.cpp:693
bool IsCancelled() const
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition: drc_item.cpp:393
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
virtual ~DRC_TEST_PROVIDER_TEXT_DIMS()=default
virtual const wxString GetName() const override
Represent a DRC "provider" which runs some DRC functions over a BOARD and spits out DRC_ITEM and posi...
virtual bool reportPhase(const wxString &aStageName)
virtual void reportViolation(std::shared_ptr< DRC_ITEM > &item, const VECTOR2I &aMarkerPos, int aMarkerLayer, DRC_CUSTOM_MARKER_HANDLER *aCustomHandler=nullptr)
int forEachGeometryItem(const std::vector< KICAD_T > &aTypes, const LSET &aLayers, const std::function< bool(BOARD_ITEM *)> &aFunc)
DRC_ENGINE * m_drcEngine
wxString formatMsg(const wxString &aFormatString, const wxString &aSource, double aConstraint, double aActual, EDA_DATA_TYPE aDataType=EDA_DATA_TYPE::DISTANCE)
virtual bool reportProgress(size_t aCount, size_t aSize, size_t aDelta=1)
virtual VECTOR2I GetPosition() const
Definition: eda_item.h:259
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:79
FONT is an abstract base class for both outline and stroke fonts.
Definition: font.h:131
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
Definition: font.cpp:147
virtual bool IsOutline() const
Definition: font.h:139
static const LSET & AllLayersMask()
Definition: lset.cpp:627
T Min() const
Definition: minoptmax.h:33
bool HasMax() const
Definition: minoptmax.h:38
bool HasMin() const
Definition: minoptmax.h:37
T Max() const
Definition: minoptmax.h:34
Represent a set of closed polygons.
double Area()
Return the area of this poly set.
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
void Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
int OutlineCount() const
Return the number of outlines in the set.
SHAPE_POLY_SET CloneDropTriangulation() const
@ DRCE_TEXT_HEIGHT
Definition: drc_item.h:99
@ DRCE_TEXT_THICKNESS
Definition: drc_item.h:100
@ TEXT_THICKNESS_CONSTRAINT
Definition: drc_rule.h:58
@ TEXT_HEIGHT_CONSTRAINT
Definition: drc_rule.h:57
#define REPORT_AUX(s)
#define _(s)
This file contains miscellaneous commonly used macros and functions.
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:393
@ RPT_SEVERITY_IGNORE
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:93
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition: typeinfo.h:90
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition: typeinfo.h:95
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition: typeinfo.h:100