1 /**
2  * Functions to draw and plot text on screen
3  * @file draw_graphic_text.cpp
4  */
5 
6 /*
7  * This program source code file is part of KiCad, a free EDA CAD application.
8  *
9  * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
10  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
11  * Copyright (C) 2012 Wayne Stambaugh <stambaughw@gmail.com>
12  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, you may find one here:
26  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
27  * or you may search the http://www.gnu.org website for the version 2 license,
28  * or you may write to the Free Software Foundation, Inc.,
29  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
30  */
31 
32 #include <gr_basic.h>
33 #include <plotters/plotter.h>
34 #include <eda_text.h>           // EDA_TEXT_HJUSTIFY_T and EDA_TEXT_VJUSTIFY_T
35 #include <trigo.h>
36 #include <base_screen.h>
37 #include <math/util.h>          // for KiROUND
38 
39 #include <basic_gal.h>
40 
41 
42 /**
43  * @param aTextSize is the char size (height or width).
44  * @return the "best" value for a pen size to draw/plot a bold text.
45  */
GetPenSizeForBold(int aTextSize)46 int GetPenSizeForBold( int aTextSize )
47 {
48     return KiROUND( aTextSize / 5.0 );
49 }
50 
51 
GetPenSizeForNormal(int aTextSize)52 int GetPenSizeForNormal( int aTextSize )
53 {
54     return KiROUND( aTextSize / 8.0 );
55 }
56 
57 
58 /**
59  * Don't allow text to become cluttered up in its own fatness.  Bold fonts are generally around
60  * aSize/5 in width, so we limit them to aSize/4, and normal text to aSize/6.
61  *
62  * @param aPenSize is the pen size to clamp.
63  * @param aSize is the character size (height or width).
64  * @param aBold use true if text accept bold pen size.
65  * @return the max pen size allowed.
66  */
Clamp_Text_PenSize(int aPenSize,int aSize,bool aBold)67 int Clamp_Text_PenSize( int aPenSize, int aSize, bool aBold )
68 {
69     double scale    = aBold ? 4.0 : 6.0;
70     int    maxWidth = KiROUND( (double) aSize / scale );
71 
72     return std::min( aPenSize, maxWidth );
73 }
74 
75 
Clamp_Text_PenSize(float aPenSize,int aSize,bool aBold)76 float Clamp_Text_PenSize( float aPenSize, int aSize, bool aBold )
77 {
78     float scale    = aBold ? 4.0 : 6.0;
79     float maxWidth = (float) aSize / scale;
80 
81     return std::min( aPenSize, maxWidth );
82 }
83 
84 
Clamp_Text_PenSize(int aPenSize,const wxSize & aSize,bool aBold)85 int Clamp_Text_PenSize( int aPenSize, const wxSize& aSize, bool aBold )
86 {
87     int size = std::min( std::abs( aSize.x ), std::abs( aSize.y ) );
88 
89     return Clamp_Text_PenSize( aPenSize, size, aBold );
90 }
91 
92 
GraphicTextWidth(const wxString & aText,const wxSize & aSize,bool aItalic,bool aBold)93 int GraphicTextWidth( const wxString& aText, const wxSize& aSize, bool aItalic, bool aBold )
94 {
95     basic_gal.SetFontItalic( aItalic );
96     basic_gal.SetFontBold( aBold );
97     basic_gal.SetGlyphSize( VECTOR2D( aSize ) );
98 
99     VECTOR2D tsize = basic_gal.GetTextLineSize( aText );
100 
101     return KiROUND( tsize.x );
102 }
103 
104 
105 /**
106  * Draw a graphic text (like footprint texts).
107  *
108  *  @param aDC is the current Device Context. NULL if draw within a 3D GL Canvas.
109  *  @param aPos is the text position (according to h_justify, v_justify).
110  *  @param aColor is the text color.
111  *  @param aText is the text to draw.
112  *  @param aOrient is the angle in 0.1 degree.
113  *  @param aSize is the text size (size.x or size.y can be < 0 for mirrored texts).
114  *  @param aH_justify is the horizontal justification (Left, center, right).
115  *  @param aV_justify is the vertical justification (bottom, center, top).
116  *  @param aWidth is the line width (pen width) (use default width if aWidth = 0).
117  *      if width < 0 : draw segments in sketch mode, width = abs(width)
118  *      Use a value min(aSize.x, aSize.y) / 5 for a bold text.
119  *  @param aItalic is the true to simulate an italic font.
120  *  @param aBold use true to use a bold font. Useful only with default width value (aWidth = 0).
121  *  @param aCallback( int x0, int y0, int xf, int yf, void* aData ) is a function called
122  *                  (if non null) to draw each segment. used to draw 3D texts or for plotting.
123  *                  NULL for normal drawings
124  *  @param aCallbackData is the auxiliary parameter aData for the callback function.
125  *                       can be nullptr if no auxiliary parameter is needed
126  *  @param aPlotter is a PLOTTER instance, when this function is used to plot
127  *                  the text. NULL to draw this text.
128  */
GRText(wxDC * aDC,const wxPoint & aPos,const COLOR4D & aColor,const wxString & aText,double aOrient,const wxSize & aSize,enum EDA_TEXT_HJUSTIFY_T aH_justify,enum EDA_TEXT_VJUSTIFY_T aV_justify,int aWidth,bool aItalic,bool aBold,void (* aCallback)(int x0,int y0,int xf,int yf,void * aData),void * aCallbackData,PLOTTER * aPlotter)129 void GRText( wxDC* aDC, const wxPoint& aPos, const COLOR4D& aColor, const wxString& aText,
130              double aOrient, const wxSize& aSize, enum EDA_TEXT_HJUSTIFY_T aH_justify,
131              enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic, bool aBold,
132              void (* aCallback)( int x0, int y0, int xf, int yf, void* aData ),
133              void* aCallbackData, PLOTTER* aPlotter )
134 {
135     bool fill_mode = true;
136 
137     if( aWidth == 0 && aBold ) // Use default values if aWidth == 0
138         aWidth = GetPenSizeForBold( std::min( aSize.x, aSize.y ) );
139 
140     if( aWidth < 0 )
141     {
142         aWidth = -aWidth;
143         fill_mode = false;
144     }
145 
146     basic_gal.SetIsFill( fill_mode );
147     basic_gal.SetLineWidth( aWidth );
148 
149     EDA_TEXT dummy;
150     dummy.SetItalic( aItalic );
151     dummy.SetBold( aBold );
152     dummy.SetHorizJustify( aH_justify );
153     dummy.SetVertJustify( aV_justify );
154 
155     wxSize size = aSize;
156     dummy.SetMirrored( size.x < 0 );
157 
158     if( size.x < 0 )
159         size.x = - size.x;
160 
161     dummy.SetTextSize( size );
162 
163     basic_gal.SetTextAttributes( &dummy );
164     basic_gal.SetPlotter( aPlotter );
165     basic_gal.SetCallback( aCallback, aCallbackData );
166     basic_gal.m_DC = aDC;
167     basic_gal.m_Color = aColor;
168     basic_gal.SetClipBox( nullptr );
169     basic_gal.StrokeText( aText, VECTOR2D( aPos ), aOrient * M_PI/1800 );
170 }
171 
172 
GRHaloText(wxDC * aDC,const wxPoint & aPos,const COLOR4D & aBgColor,const COLOR4D & aColor1,const COLOR4D & aColor2,const wxString & aText,double aOrient,const wxSize & aSize,enum EDA_TEXT_HJUSTIFY_T aH_justify,enum EDA_TEXT_VJUSTIFY_T aV_justify,int aWidth,bool aItalic,bool aBold,void (* aCallback)(int x0,int y0,int xf,int yf,void * aData),void * aCallbackData,PLOTTER * aPlotter)173 void GRHaloText( wxDC* aDC, const wxPoint &aPos, const COLOR4D& aBgColor, const COLOR4D& aColor1,
174                  const COLOR4D& aColor2, const wxString &aText, double aOrient, const wxSize &aSize,
175                  enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify,
176                  int aWidth, bool aItalic, bool aBold,
177                  void (*aCallback)( int x0, int y0, int xf, int yf, void* aData ),
178                  void* aCallbackData, PLOTTER * aPlotter )
179 {
180     COLOR4D color1 = aColor1;
181     COLOR4D color2 = aColor2;
182 
183     // Swap color if contrast would be better
184     // TODO: Maybe calculate contrast some way other than brightness
185     if( aBgColor.GetBrightness() > 0.5 )
186     {
187         COLOR4D c = color1;
188         color1 = color2;
189         color2 = c;
190     }
191 
192     // Draw the background
193     GRText( aDC, aPos, color1, aText, aOrient, aSize, aH_justify, aV_justify, aWidth, aItalic,
194             aBold, aCallback, aCallbackData, aPlotter );
195 
196     // Draw the text
197     GRText( aDC, aPos, color2, aText, aOrient, aSize, aH_justify, aV_justify, aWidth / 4, aItalic,
198             aBold, aCallback, aCallbackData, aPlotter );
199 }
200 
201 
202 /**
203  * Same as GRText, but plot graphic text instead of draw it.
204  *
205  * @param aPos is the text position (according to aH_justify, aV_justify).
206  * @param aColor is the text color.
207  * @param aText is the text to draw.
208  * @param aOrient is the angle in 0.1 degree.
209  * @param aSize is the text size (size.x or size.y can be < 0 for mirrored texts).
210  * @param aH_justify is the horizontal justification (Left, center, right).
211  * @param aV_justify is the vertical justification (bottom, center, top).
212  * @param aPenWidth is the line width (if = 0, use plot default line width).
213  * @param aItalic is the true to simulate an italic font.
214  * @param aBold use true to use a bold font Useful only with default width value (aWidth = 0).
215  * @param aMultilineAllowed use true to plot text as multiline, otherwise single line.
216  * @param aData is a parameter used by some plotters in SetCurrentLineWidth(),
217  *              not directly used here.
218  */
Text(const wxPoint & aPos,const COLOR4D & aColor,const wxString & aText,double aOrient,const wxSize & aSize,enum EDA_TEXT_HJUSTIFY_T aH_justify,enum EDA_TEXT_VJUSTIFY_T aV_justify,int aPenWidth,bool aItalic,bool aBold,bool aMultilineAllowed,void * aData)219 void PLOTTER::Text( const wxPoint&              aPos,
220                     const COLOR4D&              aColor,
221                     const wxString&             aText,
222                     double                      aOrient,
223                     const wxSize&               aSize,
224                     enum EDA_TEXT_HJUSTIFY_T    aH_justify,
225                     enum EDA_TEXT_VJUSTIFY_T    aV_justify,
226                     int                         aPenWidth,
227                     bool                        aItalic,
228                     bool                        aBold,
229                     bool                        aMultilineAllowed,
230                     void*                       aData )
231 {
232     SetColor( aColor );
233     SetCurrentLineWidth( aPenWidth, aData );
234 
235     GRText( nullptr, aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, aPenWidth,
236             aItalic, aBold, nullptr, nullptr, this );
237 }
238