44constexpr double MASTER_EM = 300.0;
45constexpr double HEIGHT_DIVISOR = 222.0;
46constexpr double CALIBRI_HEIGHT_DIVISOR = 241.0;
49constexpr int FONT_WEIGHT_PER_WEIGHT = 35;
50constexpr int BOLD_FONT_WEIGHT = 551;
53constexpr int PROBE_SIZE = 1000000;
56constexpr double STROKE_PER_WEIGHT = 0.01;
59constexpr int DEFAULT_WEIGHT = 10;
61constexpr double DIN_CAP_HEIGHT = 0.9;
64constexpr double DIN_WIDTH = 0.68;
67constexpr double DIN_GAP = 0.1;
68constexpr double DIN_SPACE = 0.43;
71constexpr double DIN_GRID = 0.045;
72constexpr int DIN_DEFAULT_UNITS = 8;
74constexpr std::pair<wchar_t, int> DIN_UNITS[] = {
75 {
'!', 0 }, {
'(', 4 }, {
')', 4 }, {
'+', 10 }, {
',', 2 }, {
'-', 9 }, {
'.', 0 }, {
'/', 9 },
76 {
'1', 4 }, {
':', 2 }, {
';', 2 }, {
'A', 14 }, {
'B', 10 }, {
'C', 10 }, {
'D', 10 }, {
'E', 10 },
77 {
'F', 10 }, {
'G', 10 }, {
'H', 10 }, {
'I', 0 }, {
'K', 10 }, {
'L', 9 }, {
'M', 14 }, {
'N', 10 },
78 {
'O', 10 }, {
'P', 10 }, {
'Q', 10 }, {
'R', 10 }, {
'S', 10 }, {
'T', 10 }, {
'U', 10 }, {
'V', 10 },
79 {
'W', 20 }, {
'X', 10 }, {
'Z', 10 }, {
'_', 19 }, {
'a', 10 }, {
'f', 6 }, {
'i', 0 }, {
'k', 9 },
80 {
'l', 3 }, {
'm', 16 }, {
'r', 5 }, {
't', 6 }, {
'v', 10 }, {
'w', 16 }, {
'y', 10 }, {
'z', 9 },
81 {
L'\u00B5', 10 }, {
L'\u00E4', 10 }
85constexpr std::pair<char, int> AVERAGE_WIDTH_WEIGHTS[] = {
86 {
'a', 64 }, {
'b', 14 }, {
'c', 27 }, {
'd', 35 }, {
'e', 100 }, {
'f', 20 }, {
'g', 14 },
87 {
'h', 42 }, {
'i', 63 }, {
'j', 3 }, {
'k', 6 }, {
'l', 35 }, {
'm', 20 }, {
'n', 56 },
88 {
'o', 56 }, {
'p', 17 }, {
'q', 4 }, {
'r', 49 }, {
's', 56 }, {
't', 71 }, {
'u', 31 },
89 {
'v', 10 }, {
'w', 18 }, {
'x', 3 }, {
'y', 18 }, {
'z', 2 }, {
' ', 166 }
94std::vector<double> dinCentres(
const wxString& aText,
double aSize,
double aPen )
96 std::vector<double> centres;
99 for( wxUniChar c : aText )
103 cursor += DIN_SPACE * aSize;
107 int units = DIN_DEFAULT_UNITS;
109 for(
const auto& [ch, chUnits] : DIN_UNITS )
111 if( c.GetValue() == wxUniChar::value_type( ch ) )
118 double glyphWidth = units * DIN_GRID * aSize;
120 centres.push_back(
cursor + glyphWidth / 2.0 );
121 cursor += glyphWidth + DIN_GAP * aSize + aPen;
129std::vector<std::pair<double, double>> strokeSpans(
const wxString& aText )
131 std::vector<std::unique_ptr<KIFONT::GLYPH>> glyphs;
132 std::vector<std::pair<double, double>> spans;
137 for(
const std::unique_ptr<KIFONT::GLYPH>& glyph : glyphs )
139 std::pair<double, double> span( std::numeric_limits<double>::max(), std::numeric_limits<double>::lowest() );
145 span.first = std::min( span.first, pt.x );
146 span.second = std::max( span.second, pt.x );
150 if( span.first <= span.second )
151 spans.push_back( span );
167 double height = double( t.
height ) / aUnit;
168 double width = double( t.
width ) / aUnit;
170 double strokeBase = width;
172 if(
ToWx( t.
font ).Trim().Trim(
false ).IsSameAs( wxS(
"DIN-ISO-ANSI" ),
false ) )
174 double scale = std::max( height, width );
175 double pen =
scale * weight * STROKE_PER_WEIGHT;
176 std::vector<double> din = dinCentres( aText->
GetText(),
scale, pen );
177 std::vector<std::pair<double, double>> spans = strokeSpans( aText->
GetText() );
178 double stem = strokeSpans( wxS(
"H" ) ).front().first;
186 if( din.size() > 1 && din.size() == spans.size() )
188 for(
size_t ii = 0; ii < din.size(); ++ii )
190 double centre = ( spans[ii].first + spans[ii].second ) / 2.0 - stem;
192 cross += centre * din[ii];
193 norm += centre * centre;
197 if( cross > 0.0 && norm > 0.0 )
198 size.
x = cross / norm * PROBE_SIZE;
204 double pitch = width * ( 1.0 + 2.0 * STROKE_PER_WEIGHT * weight );
211 size.
x = pitch *
text.length() * PROBE_SIZE /
end.x;
252 wxString key =
name.Upper();
254 if( key.IsEmpty() || key == wxS(
"TARGET" ) || key == wxS(
"DIN-ISO-ANSI" ) )
258 bool bold = t.
weight * FONT_WEIGHT_PER_WEIGHT >= BOLD_FONT_WEIGHT;
260 auto fontKey = std::make_tuple( key, bold, italic );
261 auto fontIt =
m_fonts.find( fontKey );
269 fontIt =
m_fonts.emplace( fontKey, outline ).first;
283 for(
const auto& [ch, share] : AVERAGE_WIDTH_WEIGHTS )
288 total += double(
end.x ) * share;
291 widthIt =
m_averageWidth.emplace( outline, total / 1000.0 / PROBE_SIZE ).first;
294 double divisor = key == wxS(
"CALIBRI" ) ? CALIBRI_HEIGHT_DIVISOR : HEIGHT_DIVISOR;
295 double em = MASTER_EM / divisor * t.
height / aUnit;
296 double width = widthIt->second > 0.0 ? double( t.
width ) / aUnit / widthIt->second : double( t.
width ) / aUnit;
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
constexpr coord_type GetLeft() const
constexpr coord_type GetBottom() const
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
virtual void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
virtual const wxString & GetText() const
Return the string associated with the text object.
virtual void SetTextPos(const VECTOR2I &aPoint)
KIFONT::FONT * GetFont() const
void SetMirrored(bool isMirrored)
virtual EDA_ANGLE GetDrawRotation() const
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
GR_TEXT_H_ALIGN_T GetHorizJustify() const
void SetBoldFlag(bool aBold)
Set only the bold flag, without changing the font.
virtual void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
void SetItalicFlag(bool aItalic)
Set only the italic flag, without changing the font.
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
std::shared_ptr< SHAPE_COMPOUND > GetEffectiveTextShape(bool aTriangulate=true, const BOX2I &aBBox=BOX2I(), const EDA_ANGLE &aAngle=ANGLE_0) const
Build a list of segments (SHAPE_SEGMENT) to describe a text shape.
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetFont(KIFONT::FONT *aFont)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
FONT is an abstract base class for both outline and stroke fonts.
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
virtual bool IsStroke() const
virtual bool IsOutline() const
virtual VECTOR2I GetTextAsGlyphs(BOX2I *aBBox, std::vector< std::unique_ptr< GLYPH > > *aGlyphs, const wxString &aText, const VECTOR2I &aSize, const VECTOR2I &aPosition, const EDA_ANGLE &aAngle, bool aMirror, const VECTOR2I &aOrigin, TEXT_STYLE_FLAGS aTextStyle) const =0
Convert text string to an array of GLYPHs.
Implement outline font drawing.
VECTOR2I GetTextAsGlyphs(BOX2I *aBoundingBox, std::vector< std::unique_ptr< GLYPH > > *aGlyphs, const wxString &aText, const VECTOR2I &aSize, const VECTOR2I &aPosition, const EDA_ANGLE &aAngle, bool aMirror, const VECTOR2I &aOrigin, TEXT_STYLE_FLAGS aTextStyle) const override
Convert text string to an array of GLYPHs.
double GetEmSize(double aSize) const
Edge of the em square for glyphs drawn at text size aSize.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
bool applyTrueType(EDA_TEXT *aText, const ELEMENT &aElem, int aUnit)
static VECTOR2I BaselineShift(const EDA_TEXT &aText)
Offset in text units that moves aText so the baseline-left point of its first glyph lies on its posit...
std::map< std::tuple< wxString, bool, bool >, KIFONT::OUTLINE_FONT * > m_fonts
std::map< const KIFONT::OUTLINE_FONT *, double > m_averageWidth
per unit of text size
void Apply(EDA_TEXT *aText, const ELEMENT &aElem, int aUnit)
Give aText the font, style, size and stroke width of text aElem.
static constexpr EDA_ANGLE ANGLE_0
wxString ToWx(const std::string &aRaw)
Convert a stored ANSI string to a wxString.
bool FlagProp(const std::string &aKey) const
True when property aKey holds one of the format's boolean true words.
One element of any class.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D