KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_pcb_textbox.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, see AUTHORS.TXT for contributors.
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, see <https://www.gnu.org/licenses/>.
18 */
19
21#include <board.h>
22#include <pcb_textbox.h>
23
24
26{
29
31 m_board(),
33 {
34 m_textbox.SetText( wxT( "Hello World" ) );
35 m_textbox.SetTextSize( VECTOR2I( pcbIUScale.mmToIU( 1.0 ), pcbIUScale.mmToIU( 1.0 ) ) );
36 m_textbox.SetStart( VECTOR2I( 0, 0 ) );
37 m_textbox.SetEnd( VECTOR2I( pcbIUScale.mmToIU( 20.0 ), pcbIUScale.mmToIU( 5.0 ) ) );
38 }
39};
40
41
42BOOST_FIXTURE_TEST_SUITE( PcbTextbox, PCB_TEXTBOX_FIXTURE )
43
44
45// Width is unconstrained so text can rewrap, height is bounded by the wrapped content.
46BOOST_AUTO_TEST_CASE( GetMinSizeReturnsHeightOnly )
47{
48 VECTOR2I minSize = m_textbox.GetMinSize();
49
51 BOOST_CHECK_GT( minSize.y, 0 );
52}
53
54
55BOOST_AUTO_TEST_CASE( GetMinSizeGrowsWithMoreText )
56{
57 VECTOR2I minSizeShort = m_textbox.GetMinSize();
58
59 m_textbox.SetText( wxT( "Hello World\nSecond Line\nThird Line" ) );
60 m_textbox.ClearBoundingBoxCache();
61 m_textbox.ClearRenderCache();
62 VECTOR2I minSizeLong = m_textbox.GetMinSize();
63
64 BOOST_CHECK_GT( minSizeLong.y, minSizeShort.y );
65}
66
67
68BOOST_AUTO_TEST_CASE( GetMinSizeIncludesMargins )
69{
70 m_textbox.SetText( wxT( "A" ) );
71 m_textbox.SetMarginLeft( 0 );
72 m_textbox.SetMarginRight( 0 );
73 m_textbox.SetMarginTop( 0 );
74 m_textbox.SetMarginBottom( 0 );
75 m_textbox.ClearBoundingBoxCache();
76 m_textbox.ClearRenderCache();
77
78 VECTOR2I minSizeNoMargin = m_textbox.GetMinSize();
79
80 int margin = pcbIUScale.mmToIU( 1.0 );
81 m_textbox.SetMarginTop( margin );
82 m_textbox.SetMarginBottom( margin );
83 m_textbox.ClearBoundingBoxCache();
84 m_textbox.ClearRenderCache();
85
86 VECTOR2I minSizeWithMargin = m_textbox.GetMinSize();
87
88 BOOST_CHECK_EQUAL( minSizeNoMargin.x, 0 );
89 BOOST_CHECK_EQUAL( minSizeWithMargin.x, 0 );
90 BOOST_CHECK_GT( minSizeWithMargin.y, minSizeNoMargin.y );
91}
92
93
94BOOST_AUTO_TEST_CASE( GetMinSizeHeightAtLeastTextHeight )
95{
96 m_textbox.SetText( wxT( "A" ) );
97 m_textbox.ClearBoundingBoxCache();
98 m_textbox.ClearRenderCache();
99 VECTOR2I minSize = m_textbox.GetMinSize();
100
101 BOOST_CHECK_GE( minSize.y, m_textbox.GetTextSize().y );
102}
103
104
105BOOST_AUTO_TEST_CASE( GetMinSizeEmptyText )
106{
107 m_textbox.SetText( wxT( "" ) );
108 m_textbox.ClearBoundingBoxCache();
109 m_textbox.ClearRenderCache();
110
111 VECTOR2I minSize = m_textbox.GetMinSize();
112
115}
116
117
118// At 0 degrees the bound is on y, at 90 degrees it moves to x.
119BOOST_AUTO_TEST_CASE( GetMinSizeRotated90 )
120{
121 m_textbox.SetText( wxT( "Wide Text" ) );
122 m_textbox.ClearBoundingBoxCache();
123 m_textbox.ClearRenderCache();
124
125 VECTOR2I minSize0 = m_textbox.GetMinSize();
126
127 m_textbox.SetTextAngle( EDA_ANGLE( 90.0, DEGREES_T ) );
128 m_textbox.ClearBoundingBoxCache();
129 m_textbox.ClearRenderCache();
130
131 VECTOR2I minSize90 = m_textbox.GetMinSize();
132
133 BOOST_CHECK_EQUAL( minSize0.x, 0 );
134 BOOST_CHECK_GT( minSize0.y, 0 );
135 BOOST_CHECK_GT( minSize90.x, 0 );
136 BOOST_CHECK_EQUAL( minSize90.y, 0 );
137}
138
139
140BOOST_AUTO_TEST_CASE( GetMinSizeAllowsWidthReduction )
141{
142 m_textbox.SetText( wxT( "This is a very long line of text that should exceed the box width" ) );
143 m_textbox.ClearBoundingBoxCache();
144 m_textbox.ClearRenderCache();
145
146 VECTOR2I minSize = m_textbox.GetMinSize();
147
149 BOOST_CHECK_GT( minSize.y, 0 );
150}
151
152
153// Guards a past snap-back where 3x30 degrees landed on cardinal and
154// GetCornersInSequence returned an un-rotated AABB.
155BOOST_AUTO_TEST_CASE( ThirtyDegreeIncrementsToCardinalKeepsVisualRotated )
156{
157 for( int i = 0; i < 3; ++i )
158 m_textbox.Rotate( VECTOR2I( 0, 0 ), EDA_ANGLE( 30.0, DEGREES_T ) );
159
160 BOOST_REQUIRE_CLOSE( m_textbox.GetTextAngle().AsDegrees(), 90.0, 1e-6 );
161
162 std::vector<VECTOR2I> corners = m_textbox.GetCorners();
163 BOOST_REQUIRE_EQUAL( corners.size(), 4u );
164
165 BOX2I visual;
166 for( const VECTOR2I& p : corners )
167 visual.Merge( p );
168
169 const int origW = pcbIUScale.mmToIU( 20.0 );
170 const int origH = pcbIUScale.mmToIU( 5.0 );
171 BOOST_CHECK_MESSAGE( std::abs( visual.GetWidth() - origH ) <= 1,
172 "visual width " << visual.GetWidth() << " expected " << origH );
173 BOOST_CHECK_MESSAGE( std::abs( visual.GetHeight() - origW ) <= 1,
174 "visual height " << visual.GetHeight() << " expected " << origW );
175}
176
177
178// Guards a past crash where rendering a RECTANGLE textbox at a non-cardinal
179// angle walked an empty polygon vector.
180BOOST_AUTO_TEST_CASE( NonCardinalRotationDoesNotCrash )
181{
182 m_textbox.Rotate( VECTOR2I( 0, 0 ), EDA_ANGLE( 30.0, DEGREES_T ) );
183
184 std::vector<VECTOR2I> corners = m_textbox.GetCorners();
185 BOOST_REQUIRE_EQUAL( corners.size(), 4u );
186
187 BOX2I bbox;
188 for( const VECTOR2I& p : corners )
189 bbox.Merge( p );
190
191 BOOST_CHECK_GT( bbox.GetWidth(), 0 );
192 BOOST_CHECK_GT( bbox.GetHeight(), 0 );
193
194 BOOST_CHECK_NO_THROW( m_textbox.GetDrawPos() );
195}
196
197
198BOOST_AUTO_TEST_CASE( CardinalRotationsRoundTrip )
199{
200 VECTOR2I origStart = m_textbox.GetStart();
201 VECTOR2I origEnd = m_textbox.GetEnd();
202
203 VECTOR2I pivot( pcbIUScale.mmToIU( 7.0 ), pcbIUScale.mmToIU( 11.0 ) );
204
205 for( int i = 0; i < 4; ++i )
206 m_textbox.Rotate( pivot, EDA_ANGLE( 90.0, DEGREES_T ) );
207
208 BOOST_CHECK_EQUAL( m_textbox.GetStart().x, origStart.x );
209 BOOST_CHECK_EQUAL( m_textbox.GetStart().y, origStart.y );
210 BOOST_CHECK_EQUAL( m_textbox.GetEnd().x, origEnd.x );
211 BOOST_CHECK_EQUAL( m_textbox.GetEnd().y, origEnd.y );
212}
213
214
215// The on-disk form must stay a rectangle even after a tilted rotation.
216BOOST_AUTO_TEST_CASE( NonCardinalRotationKeepsLibShapeRectangle )
217{
218 m_textbox.Rotate( VECTOR2I( 0, 0 ), EDA_ANGLE( 30.0, DEGREES_T ) );
219
220 BOOST_CHECK( m_textbox.GetLibraryShape() == SHAPE_T::RECTANGLE );
221}
222
223
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:372
constexpr size_type GetWidth() const
Definition box2.h:210
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:654
constexpr size_type GetHeight() const
Definition box2.h:211
const int minSize
Push and Shove router track width and via size dialog.
@ DEGREES_T
Definition eda_angle.h:31
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:47
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(GetMinSizeReturnsHeightOnly)
BOOST_CHECK_MESSAGE(totalMismatches==0, std::to_string(totalMismatches)+" board(s) with strategy disagreements")
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683