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.

401 lines
15 KiB

3 years ago
3 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-2022 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. namespace KIGFX
  36. {
  37. class RENDER_SETTINGS;
  38. class COLOR4D;
  39. }
  40. using KIGFX::RENDER_SETTINGS;
  41. using KIGFX::COLOR4D;
  42. // part of the kicad_plugin.h family of defines.
  43. // See kicad_plugin.h for the choice of the value
  44. // When set when calling EDA_TEXT::Format, disable writing the "hide" keyword in save file
  45. #define CTL_OMIT_HIDE (1 << 6)
  46. /**
  47. * This is the "default-of-the-default" hardcoded text size; individual
  48. * application define their own default policy starting with this
  49. * (usually with a user option or project).
  50. */
  51. #define DEFAULT_SIZE_TEXT 50 // default text height (in mils, i.e. 1/1000")
  52. #define DIM_ANCRE_TEXTE 2 // Anchor size for text
  53. /**
  54. * A mix-in class (via multiple inheritance) that handles texts such as labels, parts,
  55. * components, or footprints. Because it's a mix-in class, care is used to provide
  56. * function names (accessors) that to not collide with function names likely to be seen
  57. * in the combined derived classes.
  58. */
  59. class EDA_TEXT
  60. {
  61. public:
  62. EDA_TEXT( const EDA_IU_SCALE& aIuScale, const wxString& aText = wxEmptyString );
  63. EDA_TEXT( const EDA_TEXT& aText );
  64. virtual ~EDA_TEXT();
  65. EDA_TEXT& operator=( const EDA_TEXT& aItem );
  66. /**
  67. * Return the string associated with the text object.
  68. *
  69. * @return a const wxString reference containing the string of the item.
  70. */
  71. virtual const wxString& GetText() const { return m_text; }
  72. /**
  73. * Return the string actually shown after processing of the base text.
  74. *
  75. * @param aDepth is used to prevent infinite recursions and loops when expanding
  76. * text variables.
  77. * @param aAllowExtraText is true to allow adding more text than the initial expanded text,
  78. * for intance a title, a prefix for texts in display functions.
  79. * False to disable any added text (for instance when writing the shown text in netlists).
  80. */
  81. virtual wxString GetShownText( int aDepth = 0, bool aAllowExtraText = true ) const { return m_shown_text; }
  82. /**
  83. * Indicates the ShownText has text var references which need to be processed.
  84. */
  85. bool HasTextVars() const { return m_shown_text_has_text_var_refs; }
  86. virtual void SetText( const wxString& aText );
  87. /**
  88. * The TextThickness is that set by the user. The EffectiveTextPenWidth also factors
  89. * in bold text and thickness clamping.
  90. */
  91. void SetTextThickness( int aWidth );
  92. int GetTextThickness() const { return m_attributes.m_StrokeWidth; };
  93. /**
  94. * The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
  95. */
  96. int GetEffectiveTextPenWidth( int aDefaultPenWidth = 0 ) const;
  97. virtual void SetTextAngle( const EDA_ANGLE& aAngle );
  98. const EDA_ANGLE& GetTextAngle() const { return m_attributes.m_Angle; }
  99. void SetItalic( bool aItalic );
  100. bool IsItalic() const { return m_attributes.m_Italic; }
  101. void SetBold( bool aBold );
  102. bool IsBold() const { return m_attributes.m_Bold; }
  103. virtual void SetVisible( bool aVisible );
  104. virtual bool IsVisible() const { return m_attributes.m_Visible; }
  105. void SetMirrored( bool isMirrored );
  106. bool IsMirrored() const { return m_attributes.m_Mirrored; }
  107. /**
  108. * @param aAllow true if ok to use multiline option, false if ok to use only single line
  109. * text. (Single line is faster in calculations than multiline.)
  110. */
  111. void SetMultilineAllowed( bool aAllow );
  112. bool IsMultilineAllowed() const { return m_attributes.m_Multiline; }
  113. void SetHorizJustify( GR_TEXT_H_ALIGN_T aType );
  114. GR_TEXT_H_ALIGN_T GetHorizJustify() const { return m_attributes.m_Halign; };
  115. void SetVertJustify( GR_TEXT_V_ALIGN_T aType );
  116. GR_TEXT_V_ALIGN_T GetVertJustify() const { return m_attributes.m_Valign; };
  117. void SetKeepUpright( bool aKeepUpright );
  118. bool IsKeepUpright() const { return m_attributes.m_KeepUpright; }
  119. /**
  120. * Set the text attributes from another instance.
  121. */
  122. void SetAttributes( const EDA_TEXT& aSrc );
  123. /**
  124. * Swap the text attributes of the two involved instances.
  125. */
  126. void SwapAttributes( EDA_TEXT& aTradingPartner );
  127. void SwapText( EDA_TEXT& aTradingPartner );
  128. void CopyText( const EDA_TEXT& aSrc );
  129. void SetAttributes( const TEXT_ATTRIBUTES& aTextAttrs ) { m_attributes = aTextAttrs; }
  130. const TEXT_ATTRIBUTES& GetAttributes() const { return m_attributes; }
  131. /**
  132. * Helper function used in search and replace dialog.
  133. *
  134. * Perform a text replace using the find and replace criteria in \a aSearchData.
  135. *
  136. * @param aSearchData A reference to a EDA_SEARCH_DATA object containing the
  137. * search and replace criteria.
  138. * @return True if the text item was modified, otherwise false.
  139. */
  140. bool Replace( const EDA_SEARCH_DATA& aSearchData );
  141. bool IsDefaultFormatting() const;
  142. void SetFont( KIFONT::FONT* aFont );
  143. KIFONT::FONT* GetFont() const { return m_attributes.m_Font; }
  144. wxString GetFontName() const;
  145. void SetLineSpacing( double aLineSpacing );
  146. double GetLineSpacing() const { return m_attributes.m_LineSpacing; }
  147. void SetTextSize( const VECTOR2I& aNewSize );
  148. VECTOR2I GetTextSize() const { return m_attributes.m_Size; }
  149. void SetTextWidth( int aWidth );
  150. int GetTextWidth() const { return m_attributes.m_Size.x; }
  151. void SetTextHeight( int aHeight );
  152. int GetTextHeight() const { return m_attributes.m_Size.y; }
  153. void SetTextColor( const COLOR4D& aColor ) { m_attributes.m_Color = aColor; }
  154. COLOR4D GetTextColor() const { return m_attributes.m_Color; }
  155. void SetTextPos( const VECTOR2I& aPoint );
  156. const VECTOR2I& GetTextPos() const { return m_pos; }
  157. void SetTextX( int aX );
  158. void SetTextY( int aY );
  159. void Offset( const VECTOR2I& aOffset );
  160. void Empty();
  161. static GR_TEXT_H_ALIGN_T MapHorizJustify( int aHorizJustify );
  162. static GR_TEXT_V_ALIGN_T MapVertJustify( int aVertJustify );
  163. /**
  164. * Print this text object to the device context \a aDC.
  165. *
  166. * @param aDC the current Device Context.
  167. * @param aOffset draw offset (usually (0,0)).
  168. * @param aColor text color.
  169. * @param aDisplay_mode #FILLED or #SKETCH.
  170. */
  171. void Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset,
  172. const COLOR4D& aColor, OUTLINE_MODE aDisplay_mode = FILLED );
  173. /**
  174. * Convert the text bounding box to a rectangular polygon depending on the text
  175. * orientation, the bounding box is not always horizontal or vertical
  176. *
  177. * Used in filling zones calculations
  178. * Circles and arcs are approximated by segments
  179. *
  180. * @param aBuffer a buffer to store the polygon.
  181. * @param aClearance the clearance around the text bounding box
  182. * to the real clearance value (usually near from 1.0).
  183. */
  184. void TransformBoundingBoxToPolygon( SHAPE_POLY_SET* aBuffer, int aClearance ) const;
  185. /**
  186. * build a list of segments (SHAPE_SEGMENT) to describe a text shape.
  187. * @param aTriangulate: true to build also the triangulation of each shape
  188. * @param aUseTextRotation: true to use the actual text draw rotation.
  189. * false to build a list of shape for a not rotated text ("native" shapes).
  190. */
  191. std::shared_ptr<SHAPE_COMPOUND> GetEffectiveTextShape( bool aTriangulate = true,
  192. bool aUseTextRotation = true ) const;
  193. /**
  194. * Test if \a aPoint is within the bounds of this object.
  195. *
  196. * @param aPoint A VECTOR2I to test.
  197. * @param aAccuracy Amount to inflate the bounding box.
  198. * @return true if a hit, else false.
  199. */
  200. virtual bool TextHitTest( const VECTOR2I& aPoint, int aAccuracy = 0 ) const;
  201. /**
  202. * Test if object bounding box is contained within or intersects \a aRect.
  203. *
  204. * @param aRect Rect to test against.
  205. * @param aContains Test for containment instead of intersection if true.
  206. * @param aAccuracy Amount to inflate the bounding box.
  207. * @return true if a hit, else false.
  208. */
  209. virtual bool TextHitTest( const BOX2I& aRect, bool aContains, int aAccuracy = 0 ) const;
  210. /**
  211. * Useful in multiline texts to calculate the full text or a line area (for zones filling,
  212. * locate functions....)
  213. *
  214. * @param aLine The line of text to consider. Pass -1 for all lines.
  215. * @param aInvertY Invert the Y axis when calculating bounding box.
  216. * @return the rect containing the line of text (i.e. the position and the size of one line)
  217. * this rectangle is calculated for 0 orient text.
  218. * If orientation is not 0 the rect must be rotated to match the physical area
  219. */
  220. BOX2I GetTextBox( int aLine = -1, bool aInvertY = false ) const;
  221. /**
  222. * Return the distance between two lines of text.
  223. *
  224. * Calculates the distance (pitch) between two lines of text. This distance includes the
  225. * interline distance plus room for characters like j, {, and [. It also used for single
  226. * line text, to calculate the text bounding box.
  227. */
  228. int GetInterline() const;
  229. /**
  230. * @return a wxString with the style name( Normal, Italic, Bold, Bold+Italic).
  231. */
  232. wxString GetTextStyleName() const;
  233. /**
  234. * Populate \a aPositions with the position of each line of a multiline text, according
  235. * to the vertical justification and the rotation of the whole text.
  236. *
  237. * @param aPositions is the list to populate by the VECTOR2I positions.
  238. * @param aLineCount is the number of lines (not recalculated here for efficiency reasons.
  239. */
  240. void GetLinePositions( std::vector<VECTOR2I>& aPositions, int aLineCount ) const;
  241. /**
  242. * Output the object to \a aFormatter in s-expression form.
  243. *
  244. * @param aFormatter The #OUTPUTFORMATTER object to write to.
  245. * @param aNestLevel The indentation next level.
  246. * @param aControlBits The control bit definition for object specific formatting.
  247. * @throw IO_ERROR on write error.
  248. */
  249. virtual void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const;
  250. virtual KIFONT::FONT* GetDrawFont() const;
  251. virtual EDA_ANGLE GetDrawRotation() const { return GetTextAngle(); }
  252. virtual VECTOR2I GetDrawPos() const { return GetTextPos(); }
  253. virtual void ClearRenderCache();
  254. virtual void ClearBoundingBoxCache();
  255. std::vector<std::unique_ptr<KIFONT::GLYPH>>*
  256. GetRenderCache( const wxString& forResolvedText, const VECTOR2I& aOffset = { 0, 0 } ) const;
  257. // Support for reading the cache from disk.
  258. void SetupRenderCache( const wxString& aResolvedText, const EDA_ANGLE& aAngle );
  259. void AddRenderCacheGlyph( const SHAPE_POLY_SET& aPoly );
  260. int Compare( const EDA_TEXT* aOther ) const;
  261. virtual bool HasHyperlink() const { return !m_hyperlink.IsEmpty(); }
  262. wxString GetHyperlink() const { return m_hyperlink; }
  263. void SetHyperlink( wxString aLink ) { m_hyperlink = aLink; }
  264. void RemoveHyperlink() { m_hyperlink = wxEmptyString; }
  265. /**
  266. * Check if aURL is a valid hyperlink.
  267. *
  268. * @param aURL String to validate
  269. * @return true if aURL is a valid hyperlink
  270. */
  271. static bool ValidateHyperlink( const wxString& aURL );
  272. /**
  273. * Check if aHref is a valid internal hyperlink.
  274. *
  275. * @param aHref String to validate
  276. * @param aDestination [optional] pointer to populate with the destination page
  277. * @return true if aHref is a valid internal hyperlink. Does *not* check if the destination
  278. * page actually exists.
  279. */
  280. static bool IsGotoPageHref( const wxString& aHref, wxString* aDestination = nullptr );
  281. /**
  282. * Generate a href to a page in the current schematic.
  283. *
  284. * @param aDestination Destination sheet's page number.
  285. * @return A hyperlink href string that goes to the specified page.
  286. */
  287. static wxString GotoPageHref( const wxString& aDestination );
  288. protected:
  289. /**
  290. * A hyperlink URL. If empty, this text object is not a hyperlink.
  291. */
  292. wxString m_hyperlink;
  293. private:
  294. void cacheShownText();
  295. /**
  296. * Print each line of this EDA_TEXT.
  297. *
  298. * @param aOffset draw offset (usually (0,0)).
  299. * @param aColor text color.
  300. * @param aFillMode FILLED or SKETCH
  301. * @param aText the single line of text to draw.
  302. * @param aPos the position of this line ).
  303. */
  304. void printOneLineOfText( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset,
  305. const COLOR4D& aColor, OUTLINE_MODE aFillMode, const wxString& aText,
  306. const VECTOR2I& aPos );
  307. wxString m_text;
  308. wxString m_shown_text; // Cache of unescaped text for efficient access
  309. bool m_shown_text_has_text_var_refs;
  310. std::reference_wrapper<const EDA_IU_SCALE> m_IuScale;
  311. mutable wxString m_render_cache_text;
  312. mutable EDA_ANGLE m_render_cache_angle;
  313. mutable VECTOR2I m_render_cache_offset;
  314. mutable std::vector<std::unique_ptr<KIFONT::GLYPH>> m_render_cache;
  315. mutable bool m_bounding_box_cache_valid;
  316. mutable VECTOR2I m_bounding_box_cache_pos;
  317. mutable int m_bounding_box_cache_line;
  318. mutable bool m_bounding_box_cache_inverted;
  319. mutable BOX2I m_bounding_box_cache;
  320. TEXT_ATTRIBUTES m_attributes;
  321. VECTOR2I m_pos;
  322. };
  323. #endif // EDA_TEXT_H_