You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

473 lines
17 KiB

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