-
-
Notifications
You must be signed in to change notification settings - Fork 476
/
eda_text.h
454 lines (362 loc) · 16.5 KB
/
eda_text.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
/*
* 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-2023 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 EDA_TEXT_H_
#define EDA_TEXT_H_
#include <memory>
#include <vector>
#include <outline_mode.h>
#include <eda_search_data.h>
#include <font/glyph.h>
#include <font/text_attributes.h>
class OUTPUTFORMATTER;
class SHAPE_COMPOUND;
class SHAPE_POLY_SET;
// These are only here for algorithmic safety, not to tell the user what to do.
// PL_EDITOR has the least resolution (its internal units are microns), so the min size is chosen
// to yield 1 in PL_EDITOR.
// The max size chosen is somewhat arbitrary, but no one has complained yet.
#define TEXT_MIN_SIZE_MM 0.001 ///< Minimum text size (1 micron).
#define TEXT_MAX_SIZE_MM 250.0 ///< Maximum text size in mm (~10 inches)
namespace KIGFX
{
class RENDER_SETTINGS;
class COLOR4D;
}
namespace KIFONT
{
class METRICS;
}
using KIGFX::RENDER_SETTINGS;
using KIGFX::COLOR4D;
// part of the kicad_plugin.h family of defines.
// See kicad_plugin.h for the choice of the value
// When set when calling EDA_TEXT::Format, disable writing the "hide" keyword in save file
#define CTL_OMIT_HIDE (1 << 6)
/**
* This is the "default-of-the-default" hardcoded text size; individual application define their
* own default policy starting with this (usually with a user option or project).
*/
#define DEFAULT_SIZE_TEXT 50 // default text height (in mils, i.e. 1/1000")
/**
* A mix-in class (via multiple inheritance) that handles texts such as labels, parts,
* components, or footprints. Because it's a mix-in class, care is used to provide
* function names (accessors) that to not collide with function names likely to be seen
* in the combined derived classes.
*/
class EDA_TEXT
{
public:
EDA_TEXT( const EDA_IU_SCALE& aIuScale, const wxString& aText = wxEmptyString );
EDA_TEXT( const EDA_TEXT& aText );
virtual ~EDA_TEXT();
EDA_TEXT& operator=( const EDA_TEXT& aItem );
/**
* Return the string associated with the text object.
*
* @return a const wxString reference containing the string of the item.
*/
virtual const wxString& GetText() const { return m_text; }
/**
* Return the string actually shown after processing of the base text.
*
* @param aAllowExtraText is true to allow adding more text than the initial expanded text,
* for intance a title, a prefix for texts in display functions.
* False to disable any added text (for instance when writing the shown text in netlists).
* @param aDepth is used to prevent infinite recursions and loops when expanding
* text variables.
*/
virtual wxString GetShownText( bool aAllowExtraText, int aDepth = 0 ) const
{
return m_shown_text;
}
/**
* Indicates the ShownText has text var references which need to be processed.
*/
bool HasTextVars() const { return m_shown_text_has_text_var_refs; }
virtual void SetText( const wxString& aText );
/**
* The TextThickness is that set by the user. The EffectiveTextPenWidth also factors
* in bold text and thickness clamping.
*/
void SetTextThickness( int aWidth );
int GetTextThickness() const { return m_attributes.m_StrokeWidth; };
/**
* The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
*/
int GetEffectiveTextPenWidth( int aDefaultPenWidth = 0 ) const;
virtual void SetTextAngle( const EDA_ANGLE& aAngle );
const EDA_ANGLE& GetTextAngle() const { return m_attributes.m_Angle; }
// For property system:
void SetTextAngleDegrees( double aOrientation )
{
SetTextAngle( EDA_ANGLE( aOrientation, DEGREES_T ) );
}
double GetTextAngleDegrees() const { return m_attributes.m_Angle.AsDegrees(); }
void SetItalic( bool aItalic );
bool IsItalic() const { return m_attributes.m_Italic; }
void SetBold( bool aBold );
void SetBoldFlag( bool aBold );
bool IsBold() const { return m_attributes.m_Bold; }
virtual void SetVisible( bool aVisible );
virtual bool IsVisible() const { return m_attributes.m_Visible; }
void SetMirrored( bool isMirrored );
bool IsMirrored() const { return m_attributes.m_Mirrored; }
/**
* @param aAllow true if ok to use multiline option, false if ok to use only single line
* text. (Single line is faster in calculations than multiline.)
*/
void SetMultilineAllowed( bool aAllow );
bool IsMultilineAllowed() const { return m_attributes.m_Multiline; }
void SetHorizJustify( GR_TEXT_H_ALIGN_T aType );
GR_TEXT_H_ALIGN_T GetHorizJustify() const { return m_attributes.m_Halign; };
void SetVertJustify( GR_TEXT_V_ALIGN_T aType );
GR_TEXT_V_ALIGN_T GetVertJustify() const { return m_attributes.m_Valign; };
void SetKeepUpright( bool aKeepUpright );
bool IsKeepUpright() const { return m_attributes.m_KeepUpright; }
void FlipHJustify()
{
if( GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
else if( GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT )
SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
}
/**
* Set the text attributes from another instance.
*/
void SetAttributes( const EDA_TEXT& aSrc, bool aSetPosition = true );
/**
* Swap the text attributes of the two involved instances.
*/
void SwapAttributes( EDA_TEXT& aTradingPartner );
void SwapText( EDA_TEXT& aTradingPartner );
void CopyText( const EDA_TEXT& aSrc );
void SetAttributes( const TEXT_ATTRIBUTES& aTextAttrs ) { m_attributes = aTextAttrs; }
const TEXT_ATTRIBUTES& GetAttributes() const { return m_attributes; }
/**
* Helper function used in search and replace dialog.
*
* Perform a text replace using the find and replace criteria in \a aSearchData.
*
* @param aSearchData A reference to a EDA_SEARCH_DATA object containing the
* search and replace criteria.
* @return True if the text item was modified, otherwise false.
*/
bool Replace( const EDA_SEARCH_DATA& aSearchData );
bool IsDefaultFormatting() const;
void SetFont( KIFONT::FONT* aFont );
KIFONT::FONT* GetFont() const { return m_attributes.m_Font; }
wxString GetFontName() const;
void SetFontIndex( int aIdx );
int GetFontIndex() const;
void SetLineSpacing( double aLineSpacing );
double GetLineSpacing() const { return m_attributes.m_LineSpacing; }
void SetTextSize( VECTOR2I aNewSize, bool aEnforceMinTextSize = true );
VECTOR2I GetTextSize() const { return m_attributes.m_Size; }
void SetTextWidth( int aWidth );
int GetTextWidth() const { return m_attributes.m_Size.x; }
void SetTextHeight( int aHeight );
int GetTextHeight() const { return m_attributes.m_Size.y; }
void SetTextColor( const COLOR4D& aColor ) { m_attributes.m_Color = aColor; }
COLOR4D GetTextColor() const { return m_attributes.m_Color; }
void SetTextPos( const VECTOR2I& aPoint );
const VECTOR2I& GetTextPos() const { return m_pos; }
void SetTextX( int aX );
void SetTextY( int aY );
void Offset( const VECTOR2I& aOffset );
void Empty();
static GR_TEXT_H_ALIGN_T MapHorizJustify( int aHorizJustify );
static GR_TEXT_V_ALIGN_T MapVertJustify( int aVertJustify );
/**
* Print this text object to the device context \a aDC.
*
* @param aDC the current Device Context.
* @param aOffset draw offset (usually (0,0)).
* @param aColor text color.
* @param aDisplay_mode #FILLED or #SKETCH.
*/
void Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset, const COLOR4D& aColor,
OUTLINE_MODE aDisplay_mode = FILLED );
/**
* build a list of segments (SHAPE_SEGMENT) to describe a text shape.
* @param aTriangulate: true to build also the triangulation of each shape
* @param aUseTextRotation: true to use the actual text draw rotation.
* false to build a list of shape for a not rotated text ("native" shapes).
*/
std::shared_ptr<SHAPE_COMPOUND> GetEffectiveTextShape( bool aTriangulate = true,
const BOX2I& aBBox = BOX2I(),
const EDA_ANGLE& aAngle = ANGLE_0 ) const;
/**
* Test if \a aPoint is within the bounds of this object.
*
* @param aPoint A VECTOR2I to test.
* @param aAccuracy Amount to inflate the bounding box.
* @return true if a hit, else false.
*/
virtual bool TextHitTest( const VECTOR2I& aPoint, int aAccuracy = 0 ) const;
/**
* Test if object bounding box is contained within or intersects \a aRect.
*
* @param aRect Rect to test against.
* @param aContains Test for containment instead of intersection if true.
* @param aAccuracy Amount to inflate the bounding box.
* @return true if a hit, else false.
*/
virtual bool TextHitTest( const BOX2I& aRect, bool aContains, int aAccuracy = 0 ) const;
/**
* Useful in multiline texts to calculate the full text or a line area (for zones filling,
* locate functions....)
*
* @param aLine The line of text to consider. Pass -1 for all lines.
* @return the rect containing the line of text (i.e. the position and the size of one line)
* this rectangle is calculated for 0 orient text.
* If orientation is not 0 the rect must be rotated to match the physical area
*/
BOX2I GetTextBox( int aLine = -1 ) const;
/**
* Return the distance between two lines of text.
*
* Calculates the distance (pitch) between two lines of text. This distance includes the
* interline distance plus room for characters like j, {, and [. It also used for single
* line text, to calculate the text bounding box.
*/
int GetInterline() const;
/**
* @return a wxString with the style name( Normal, Italic, Bold, Bold+Italic).
*/
wxString GetTextStyleName() const;
/**
* Populate \a aPositions with the position of each line of a multiline text, according
* to the vertical justification and the rotation of the whole text.
*
* @param aPositions is the list to populate by the VECTOR2I positions.
* @param aLineCount is the number of lines (not recalculated here for efficiency reasons.
*/
void GetLinePositions( std::vector<VECTOR2I>& aPositions, int aLineCount ) const;
/**
* Return the levenstein distance between two texts.
*
* Return a value of 0.0 - 1.0 where 1.0 is a perfect match.
*/
double Levenshtein( const EDA_TEXT& aOther ) const;
double Similarity( const EDA_TEXT& aOther ) const;
/**
* Output the object to \a aFormatter in s-expression form.
*
* @param aFormatter The #OUTPUTFORMATTER object to write to.
* @param aNestLevel The indentation next level.
* @param aControlBits The control bit definition for object specific formatting.
* @throw IO_ERROR on write error.
*/
virtual void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const;
virtual EDA_ANGLE GetDrawRotation() const { return GetTextAngle(); }
virtual VECTOR2I GetDrawPos() const { return GetTextPos(); }
virtual void ClearRenderCache();
virtual void ClearBoundingBoxCache();
std::vector<std::unique_ptr<KIFONT::GLYPH>>*
GetRenderCache( const KIFONT::FONT* aFont, const wxString& forResolvedText,
const VECTOR2I& aOffset = { 0, 0 } ) const;
// Support for reading the cache from disk.
void SetupRenderCache( const wxString& aResolvedText, const KIFONT::FONT* aFont,
const EDA_ANGLE& aAngle, const VECTOR2I& aOffset );
void AddRenderCacheGlyph( const SHAPE_POLY_SET& aPoly );
int Compare( const EDA_TEXT* aOther ) const;
bool operator==( const EDA_TEXT& aRhs ) const { return Compare( &aRhs ) == 0; }
bool operator<( const EDA_TEXT& aRhs ) const { return Compare( &aRhs ) < 0; }
bool operator>( const EDA_TEXT& aRhs ) const { return Compare( &aRhs ) > 0; }
virtual bool HasHyperlink() const { return !m_hyperlink.IsEmpty(); }
wxString GetHyperlink() const { return m_hyperlink; }
void SetHyperlink( wxString aLink ) { m_hyperlink = aLink; }
void RemoveHyperlink() { m_hyperlink = wxEmptyString; }
/**
* Check if aURL is a valid hyperlink.
*
* @param aURL String to validate
* @return true if aURL is a valid hyperlink
*/
static bool ValidateHyperlink( const wxString& aURL );
/**
* Check if aHref is a valid internal hyperlink.
*
* @param aHref String to validate
* @param aDestination [optional] pointer to populate with the destination page
* @return true if aHref is a valid internal hyperlink. Does *not* check if the destination
* page actually exists.
*/
static bool IsGotoPageHref( const wxString& aHref, wxString* aDestination = nullptr );
/**
* Generate a href to a page in the current schematic.
*
* @param aDestination Destination sheet's page number.
* @return A hyperlink href string that goes to the specified page.
*/
static wxString GotoPageHref( const wxString& aDestination );
protected:
virtual KIFONT::FONT* getDrawFont() const;
virtual const KIFONT::METRICS& getFontMetrics() const;
virtual void cacheShownText();
/**
* Print each line of this EDA_TEXT.
*
* @param aOffset draw offset (usually (0,0)).
* @param aColor text color.
* @param aFillMode FILLED or SKETCH
* @param aText the single line of text to draw.
* @param aPos the position of this line ).
*/
void printOneLineOfText( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset,
const COLOR4D& aColor, OUTLINE_MODE aFillMode, const wxString& aText,
const VECTOR2I& aPos );
protected:
/**
* A hyperlink URL. If empty, this text object is not a hyperlink.
*/
wxString m_hyperlink;
private:
wxString m_text;
wxString m_shown_text; // Cache of unescaped text for efficient access
bool m_shown_text_has_text_var_refs;
std::reference_wrapper<const EDA_IU_SCALE> m_IuScale;
mutable wxString m_render_cache_text;
mutable const KIFONT::FONT* m_render_cache_font;
mutable EDA_ANGLE m_render_cache_angle;
mutable VECTOR2I m_render_cache_offset;
mutable std::vector<std::unique_ptr<KIFONT::GLYPH>> m_render_cache;
mutable bool m_bounding_box_cache_valid;
mutable VECTOR2I m_bounding_box_cache_pos;
mutable int m_bounding_box_cache_line;
mutable BOX2I m_bounding_box_cache;
TEXT_ATTRIBUTES m_attributes;
VECTOR2I m_pos;
};
extern std::ostream& operator<<( std::ostream& aStream, const EDA_TEXT& aAttributes );
template<>
struct std::hash<EDA_TEXT>
{
std::size_t operator()( const EDA_TEXT& aText ) const
{
return hash_val( aText.GetText(), aText.GetAttributes(), aText.GetTextPos().x,
aText.GetTextPos().y );
}
};
#endif // EDA_TEXT_H_