KiCad PCB EDA Suite
Loading...
Searching...
No Matches
font.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KICAD, a free EDA CAD application.
3 *
4 * Copyright (C) 2021 Ola Rinta-Koski
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * Font abstract base class
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <list>
28#include <mutex>
29#include <unordered_map>
30
31#include <macros.h>
32#include <string_utils.h>
34#include <font/stroke_font.h>
35#include <font/outline_font.h>
36#include <trigo.h>
37#include <markup_parser.h>
38
39// The "official" name of the Kicad stroke font (always existing)
41#include <wx/tokenzr.h>
42
43// markup_parser.h includes pegtl.hpp which includes windows.h... which leaks #define DrawText
44#undef DrawText
45
46
47using namespace KIFONT;
48
50
51
53{
54 return g_defaultMetrics;
55}
56
57
58FONT* FONT::s_defaultFont = nullptr;
59
60std::map< std::tuple<wxString, bool, bool, bool>, FONT*> FONT::s_fontMap;
61
63{
64public:
65 struct ENTRY
66 {
67 std::string source;
68 std::unique_ptr<MARKUP::NODE> root;
69 };
70
71 typedef std::pair<wxString, ENTRY> CACHE_ENTRY;
72
73 MARKUP_CACHE( size_t aMaxSize ) :
74 m_maxSize( aMaxSize )
75 {
76 }
77
78 ENTRY& Put( const CACHE_ENTRY::first_type& aQuery, ENTRY&& aResult )
79 {
80 auto it = m_cache.find( aQuery );
81
82 m_cacheMru.emplace_front( CACHE_ENTRY( aQuery, std::move( aResult ) ) );
83
84 if( it != m_cache.end() )
85 {
86 m_cacheMru.erase( it->second );
87 m_cache.erase( it );
88 }
89
90 m_cache[aQuery] = m_cacheMru.begin();
91
92 if( m_cache.size() > m_maxSize )
93 {
94 auto last = m_cacheMru.end();
95 last--;
96 m_cache.erase( last->first );
97 m_cacheMru.pop_back();
98 }
99
100 return m_cacheMru.begin()->second;
101 }
102
103 ENTRY* Get( const CACHE_ENTRY::first_type& aQuery )
104 {
105 auto it = m_cache.find( aQuery );
106
107 if( it == m_cache.end() )
108 return nullptr;
109
110 m_cacheMru.splice( m_cacheMru.begin(), m_cacheMru, it->second );
111
112 return &m_cacheMru.begin()->second;
113 }
114
115 void Clear()
116 {
117 m_cacheMru.clear();
118 m_cache.clear();
119 }
120
121private:
122 size_t m_maxSize;
123 std::list<CACHE_ENTRY> m_cacheMru;
124 std::unordered_map<wxString, std::list<CACHE_ENTRY>::iterator> m_cache;
125};
126
127
129static std::mutex s_markupCacheMutex;
130
131
133{
134}
135
136
138{
139 if( !s_defaultFont )
140 s_defaultFont = STROKE_FONT::LoadFont( wxEmptyString );
141
142 return s_defaultFont;
143}
144
145
146FONT* FONT::GetFont( const wxString& aFontName, bool aBold, bool aItalic,
147 const std::vector<wxString>* aEmbeddedFiles, bool aForDrawingSheet )
148{
149 if( aFontName.empty() || aFontName.StartsWith( KICAD_FONT_NAME ) )
150 return getDefaultFont();
151
152 std::tuple<wxString, bool, bool, bool> key = { aFontName, aBold, aItalic, aForDrawingSheet };
153
154 FONT* font = nullptr;
155
156 if( s_fontMap.find( key ) != s_fontMap.end() )
157 font = s_fontMap[key];
158
159 if( !font )
160 font = OUTLINE_FONT::LoadFont( aFontName, aBold, aItalic, aEmbeddedFiles,
161 aForDrawingSheet );
162
163 if( !font )
164 font = getDefaultFont();
165
166 s_fontMap[key] = font;
167
168 return font;
169}
170
171
172bool FONT::IsStroke( const wxString& aFontName )
173{
174 // This would need a more complex implementation if we ever support more stroke fonts
175 // than the KiCad Font.
176 return aFontName == _( "Default Font" ) || aFontName == KICAD_FONT_NAME;
177}
178
179
180void FONT::getLinePositions( const wxString& aText, const VECTOR2I& aPosition,
181 wxArrayString& aTextLines, std::vector<VECTOR2I>& aPositions,
182 std::vector<VECTOR2I>& aExtents, const TEXT_ATTRIBUTES& aAttrs,
183 const METRICS& aFontMetrics ) const
184{
185 wxStringSplit( aText, aTextLines, '\n' );
186 int lineCount = aTextLines.Count();
187 aPositions.reserve( lineCount );
188
189 int interline = GetInterline( aAttrs.m_Size.y, aFontMetrics ) * aAttrs.m_LineSpacing;
190 int height = 0;
191
192 for( int i = 0; i < lineCount; i++ )
193 {
194 VECTOR2I pos( aPosition.x, aPosition.y + i * interline );
195 VECTOR2I end = boundingBoxSingleLine( nullptr, aTextLines[i], pos, aAttrs.m_Size,
196 aAttrs.m_Italic, aFontMetrics );
197 VECTOR2I bBox( end - pos );
198
199 aExtents.push_back( bBox );
200
201 if( i == 0 )
202 height += ( aAttrs.m_Size.y * 1.17 ); // 1.17 is a fudge to match 6.0 positioning
203 else
204 height += interline;
205 }
206
207 VECTOR2I offset( 0, 0 );
208 offset.y += aAttrs.m_Size.y;
209
210 if( IsStroke() )
211 {
212 // Fudge factors to match 6.0 positioning
213 offset.x += aAttrs.m_StrokeWidth / 1.52;
214 offset.y -= aAttrs.m_StrokeWidth * 0.052;
215 }
216
217 switch( aAttrs.m_Valign )
218 {
219 case GR_TEXT_V_ALIGN_TOP: break;
220 case GR_TEXT_V_ALIGN_CENTER: offset.y -= height / 2; break;
221 case GR_TEXT_V_ALIGN_BOTTOM: offset.y -= height; break;
223 wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) );
224 break;
225 }
226
227 for( int i = 0; i < lineCount; i++ )
228 {
229 VECTOR2I lineSize = aExtents.at( i );
230 VECTOR2I lineOffset( offset );
231
232 lineOffset.y += i * interline;
233
234 switch( aAttrs.m_Halign )
235 {
236 case GR_TEXT_H_ALIGN_LEFT: break;
237 case GR_TEXT_H_ALIGN_CENTER: lineOffset.x = -lineSize.x / 2; break;
238 case GR_TEXT_H_ALIGN_RIGHT: lineOffset.x = -( lineSize.x + offset.x ); break;
240 wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) );
241 break;
242 }
243
244 aPositions.push_back( aPosition + lineOffset );
245 }
246}
247
248
249void FONT::Draw( KIGFX::GAL* aGal, const wxString& aText, const VECTOR2I& aPosition,
250 const VECTOR2I& aCursor, const TEXT_ATTRIBUTES& aAttrs,
251 const METRICS& aFontMetrics ) const
252{
253 if( !aGal || aText.empty() )
254 return;
255
256 VECTOR2I position( aPosition - aCursor );
257
258 // Split multiline strings into separate ones and draw them line by line
259 wxArrayString strings_list;
260 std::vector<VECTOR2I> positions;
261 std::vector<VECTOR2I> extents;
262
263 getLinePositions( aText, position, strings_list, positions, extents, aAttrs, aFontMetrics );
264
265 aGal->SetLineWidth( aAttrs.m_StrokeWidth );
266
267 for( size_t i = 0; i < strings_list.GetCount(); i++ )
268 {
269 drawSingleLineText( aGal, nullptr, strings_list[i], positions[i], aAttrs.m_Size,
270 aAttrs.m_Angle, aAttrs.m_Mirrored, aPosition, aAttrs.m_Italic,
271 aAttrs.m_Underlined, aFontMetrics );
272 }
273}
274
275
279VECTOR2I drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
280 const MARKUP::NODE* aNode, const VECTOR2I& aPosition,
281 const KIFONT::FONT* aFont, const VECTOR2I& aSize, const EDA_ANGLE& aAngle,
282 bool aMirror, const VECTOR2I& aOrigin, TEXT_STYLE_FLAGS aTextStyle,
283 const METRICS& aFontMetrics )
284{
285 VECTOR2I nextPosition = aPosition;
286 bool drawUnderline = false;
287 bool drawOverbar = false;
288
289 if( aNode )
290 {
291 TEXT_STYLE_FLAGS textStyle = aTextStyle;
292
293 if( !aNode->is_root() )
294 {
295 if( aNode->isSubscript() )
296 textStyle |= TEXT_STYLE::SUBSCRIPT;
297 else if( aNode->isSuperscript() )
298 textStyle |= TEXT_STYLE::SUPERSCRIPT;
299
300 if( aNode->isOverbar() )
301 drawOverbar = true;
302
303 if( aNode->has_content() )
304 {
305 BOX2I bbox;
306
307 nextPosition = aFont->GetTextAsGlyphs( &bbox, aGlyphs, aNode->asWxString(), aSize,
308 nextPosition, aAngle, aMirror, aOrigin,
309 textStyle );
310
311 if( aBoundingBox )
312 aBoundingBox->Merge( bbox );
313 }
314 }
315 else if( aTextStyle & TEXT_STYLE::UNDERLINE )
316 {
317 drawUnderline = true;
318 }
319
320 for( const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
321 {
322 nextPosition = drawMarkup( aBoundingBox, aGlyphs, child.get(), nextPosition, aFont,
323 aSize, aAngle, aMirror, aOrigin, textStyle, aFontMetrics );
324 }
325 }
326
327 if( drawUnderline )
328 {
329 // Shorten the bar a little so its rounded ends don't make it over-long
330 double barTrim = aSize.x * 0.1;
331 double barOffset = aFontMetrics.GetUnderlineVerticalPosition( aSize.y );
332
333 VECTOR2D barStart( aPosition.x + barTrim, aPosition.y - barOffset );
334 VECTOR2D barEnd( nextPosition.x - barTrim, nextPosition.y - barOffset );
335
336 if( aGlyphs )
337 {
338 STROKE_GLYPH barGlyph;
339
340 barGlyph.AddPoint( barStart );
341 barGlyph.AddPoint( barEnd );
342 barGlyph.Finalize();
343
344 aGlyphs->push_back( barGlyph.Transform( { 1.0, 1.0 }, { 0, 0 }, false, aAngle, aMirror,
345 aOrigin ) );
346 }
347 }
348
349 if( drawOverbar )
350 {
351 // Shorten the bar a little so its rounded ends don't make it over-long
352 double barTrim = aSize.x * 0.1;
353 double barOffset = aFontMetrics.GetOverbarVerticalPosition( aSize.y );
354
355 VECTOR2D barStart( aPosition.x + barTrim, aPosition.y - barOffset );
356 VECTOR2D barEnd( nextPosition.x - barTrim, nextPosition.y - barOffset );
357
358 if( aGlyphs )
359 {
360 STROKE_GLYPH barGlyph;
361
362 barGlyph.AddPoint( barStart );
363 barGlyph.AddPoint( barEnd );
364 barGlyph.Finalize();
365
366 aGlyphs->push_back( barGlyph.Transform( { 1.0, 1.0 }, { 0, 0 }, false, aAngle, aMirror,
367 aOrigin ) );
368 }
369 }
370
371 return nextPosition;
372}
373
374
375VECTOR2I FONT::drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
376 const wxString& aText, const VECTOR2I& aPosition, const VECTOR2I& aSize,
377 const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
378 TEXT_STYLE_FLAGS aTextStyle, const METRICS& aFontMetrics ) const
379{
380 std::lock_guard<std::mutex> lock( s_markupCacheMutex );
381
382 MARKUP_CACHE::ENTRY* markup = s_markupCache.Get( aText );
383
384 if( !markup || !markup->root )
385 {
386 MARKUP_CACHE::ENTRY& cached = s_markupCache.Put( aText, {} );
387
388 cached.source = TO_UTF8( aText );
389 MARKUP::MARKUP_PARSER markupParser( &cached.source );
390 cached.root = markupParser.Parse();
391 markup = &cached;
392 }
393
394 wxASSERT( markup && markup->root );
395
396 return ::drawMarkup( aBoundingBox, aGlyphs, markup->root.get(), aPosition, this, aSize, aAngle,
397 aMirror, aOrigin, aTextStyle, aFontMetrics );
398}
399
400
401void FONT::drawSingleLineText( KIGFX::GAL* aGal, BOX2I* aBoundingBox, const wxString& aText,
402 const VECTOR2I& aPosition, const VECTOR2I& aSize,
403 const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
404 bool aItalic, bool aUnderline, const METRICS& aFontMetrics ) const
405{
406 if( !aGal )
407 return;
408
409 TEXT_STYLE_FLAGS textStyle = 0;
410
411 if( aItalic )
412 textStyle |= TEXT_STYLE::ITALIC;
413
414 if( aUnderline )
415 textStyle |= TEXT_STYLE::UNDERLINE;
416
417 std::vector<std::unique_ptr<GLYPH>> glyphs;
418
419 (void) drawMarkup( aBoundingBox, &glyphs, aText, aPosition, aSize, aAngle, aMirror, aOrigin,
420 textStyle, aFontMetrics );
421
422 aGal->DrawGlyphs( glyphs );
423}
424
425
426VECTOR2I FONT::StringBoundaryLimits( const wxString& aText, const VECTOR2I& aSize, int aThickness,
427 bool aBold, bool aItalic, const METRICS& aFontMetrics ) const
428{
429 // TODO do we need to parse every time - have we already parsed?
431 TEXT_STYLE_FLAGS textStyle = 0;
432
433 if( aBold )
434 textStyle |= TEXT_STYLE::BOLD;
435
436 if( aItalic )
437 textStyle |= TEXT_STYLE::ITALIC;
438
439 (void) drawMarkup( &boundingBox, nullptr, aText, VECTOR2I(), aSize, ANGLE_0, false, VECTOR2I(),
440 textStyle, aFontMetrics );
441
442 if( IsStroke() )
443 {
444 // Inflate by a bit more than thickness/2 to catch diacriticals, descenders, etc.
445 boundingBox.Inflate( KiROUND( aThickness * 1.5 ) );
446 }
447 else if( IsOutline() )
448 {
449 // Outline fonts have thickness built in, and *usually* stay within their ascent/descent
450 }
451
452 return boundingBox.GetSize();
453}
454
455
456VECTOR2I FONT::boundingBoxSingleLine( BOX2I* aBBox, const wxString& aText,
457 const VECTOR2I& aPosition, const VECTOR2I& aSize,
458 bool aItalic, const METRICS& aFontMetrics ) const
459{
460 TEXT_STYLE_FLAGS textStyle = 0;
461
462 if( aItalic )
463 textStyle |= TEXT_STYLE::ITALIC;
464
465 VECTOR2I extents = drawMarkup( aBBox, nullptr, aText, aPosition, aSize, ANGLE_0, false,
466 VECTOR2I(), textStyle, aFontMetrics );
467
468 return extents;
469}
470
471
478void wordbreakMarkup( std::vector<std::pair<wxString, int>>* aWords,
479 const std::unique_ptr<MARKUP::NODE>& aNode, const KIFONT::FONT* aFont,
480 const VECTOR2I& aSize, TEXT_STYLE_FLAGS aTextStyle )
481{
482 TEXT_STYLE_FLAGS textStyle = aTextStyle;
483
484 if( !aNode->is_root() )
485 {
486 wxChar escapeChar = 0;
487
488 if( aNode->isSubscript() )
489 {
490 escapeChar = '_';
491 textStyle = TEXT_STYLE::SUBSCRIPT;
492 }
493 else if( aNode->isSuperscript() )
494 {
495 escapeChar = '^';
496 textStyle = TEXT_STYLE::SUPERSCRIPT;
497 }
498
499 if( aNode->isOverbar() )
500 {
501 escapeChar = '~';
502 textStyle |= TEXT_STYLE::OVERBAR;
503 }
504
505 if( escapeChar )
506 {
507 wxString word = wxString::Format( wxT( "%c{" ), escapeChar );
508 int width = 0;
509
510 if( aNode->has_content() )
511 {
512 VECTOR2I next = aFont->GetTextAsGlyphs( nullptr, nullptr, aNode->asWxString(),
513 aSize, { 0, 0 }, ANGLE_0, false, { 0, 0 },
514 textStyle );
515 word += aNode->asWxString();
516 width += next.x;
517 }
518
519 std::vector<std::pair<wxString, int>> childWords;
520
521 for( const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
522 wordbreakMarkup( &childWords, child, aFont, aSize, textStyle );
523
524 for( const std::pair<wxString, int>& childWord : childWords )
525 {
526 word += childWord.first;
527 width += childWord.second;
528 }
529
530 word += wxT( "}" );
531 aWords->emplace_back( std::make_pair( word, width ) );
532 return;
533 }
534 else
535 {
536 wxString textRun = aNode->asWxString();
537 wxStringTokenizer tokenizer( textRun, " ", wxTOKEN_RET_DELIMS );
538 std::vector<wxString> words;
539
540 while( tokenizer.HasMoreTokens() )
541 words.emplace_back( tokenizer.GetNextToken() );
542
543 for( const wxString& word : words )
544 {
545 wxString chars = word;
546 chars.Trim();
547
548 int w = aFont->GetTextAsGlyphs( nullptr, nullptr, chars, aSize, { 0, 0 },
549 ANGLE_0, false, { 0, 0 }, textStyle ).x;
550
551 aWords->emplace_back( std::make_pair( word, w ) );
552 }
553 }
554 }
555
556 for( const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
557 wordbreakMarkup( aWords, child, aFont, aSize, textStyle );
558}
559
560
561void FONT::wordbreakMarkup( std::vector<std::pair<wxString, int>>* aWords, const wxString& aText,
562 const VECTOR2I& aSize, TEXT_STYLE_FLAGS aTextStyle ) const
563{
564 MARKUP::MARKUP_PARSER markupParser( TO_UTF8( aText ) );
565 std::unique_ptr<MARKUP::NODE> root = markupParser.Parse();
566
567 ::wordbreakMarkup( aWords, root, this, aSize, aTextStyle );
568}
569
570
571void FONT::LinebreakText( wxString& aText, int aColumnWidth, const VECTOR2I& aSize, int aThickness,
572 bool aBold, bool aItalic ) const
573{
574 TEXT_STYLE_FLAGS textStyle = 0;
575
576 if( aBold )
577 textStyle |= TEXT_STYLE::BOLD;
578
579 if( aItalic )
580 textStyle |= TEXT_STYLE::ITALIC;
581
582 int spaceWidth = GetTextAsGlyphs( nullptr, nullptr, wxS( " " ), aSize, VECTOR2I(), ANGLE_0,
583 false, VECTOR2I(), textStyle ).x;
584
585 wxArrayString textLines;
586 wxStringSplit( aText, textLines, '\n' );
587
588 aText = wxEmptyString;
589
590 for( size_t ii = 0; ii < textLines.Count(); ++ii )
591 {
592 std::vector<std::pair<wxString, int>> markup;
593 std::vector<std::pair<wxString, int>> words;
594
595 wordbreakMarkup( &markup, textLines[ii], aSize, textStyle );
596
597 for( const auto& [ run, runWidth ] : markup )
598 {
599 if( !words.empty() && !words.back().first.EndsWith( ' ' ) )
600 {
601 words.back().first += run;
602 words.back().second += runWidth;
603 }
604 else
605 {
606 words.emplace_back( std::make_pair( run, runWidth ) );
607 }
608 }
609
610 bool buryMode = false;
611 int lineWidth = 0;
612 wxString pendingSpaces;
613
614 for( const auto& [ word, wordWidth ] : words )
615 {
616 int pendingSpaceWidth = (int) pendingSpaces.Length() * spaceWidth;
617 bool overflow = lineWidth + pendingSpaceWidth + wordWidth > aColumnWidth - aThickness;
618
619 if( overflow && pendingSpaces.Length() > 0 )
620 {
621 aText += '\n';
622 lineWidth = 0;
623 pendingSpaces = wxEmptyString;
624 pendingSpaceWidth = 0;
625 buryMode = true;
626 }
627
628 if( word == wxS( " " ) )
629 {
630 pendingSpaces += word;
631 }
632 else
633 {
634 if( buryMode )
635 {
636 buryMode = false;
637 }
638 else
639 {
640 aText += pendingSpaces;
641 lineWidth += pendingSpaceWidth;
642 }
643
644 if( word.EndsWith( ' ' ) )
645 {
646 aText += word.Left( word.Length() - 1 );
647 pendingSpaces = wxS( " " );
648 }
649 else
650 {
651 aText += word;
652 pendingSpaces = wxEmptyString;
653 }
654
655 lineWidth += wordWidth;
656 }
657 }
658
659 // Add the newlines back onto the string
660 if( ii != ( textLines.Count() - 1 ) )
661 aText += '\n';
662 }
663}
664
665
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:558
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:658
constexpr const SizeVec & GetSize() const
Definition: box2.h:206
FONT is an abstract base class for both outline and stroke fonts.
Definition: font.h:131
VECTOR2I boundingBoxSingleLine(BOX2I *aBBox, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aSize, bool aItalic, const METRICS &aFontMetrics) const
Compute the bounding box for a single line of text.
Definition: font.cpp:456
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
Definition: font.cpp:146
void drawSingleLineText(KIGFX::GAL *aGal, BOX2I *aBoundingBox, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aSize, const EDA_ANGLE &aAngle, bool aMirror, const VECTOR2I &aOrigin, bool aItalic, bool aUnderline, const METRICS &aFontMetrics) const
Draw a single line of text.
Definition: font.cpp:401
virtual bool IsStroke() const
Definition: font.h:138
static FONT * s_defaultFont
Definition: font.h:294
void getLinePositions(const wxString &aText, const VECTOR2I &aPosition, wxArrayString &aTextLines, std::vector< VECTOR2I > &aPositions, std::vector< VECTOR2I > &aExtents, const TEXT_ATTRIBUTES &aAttrs, const METRICS &aFontMetrics) const
Definition: font.cpp:180
void wordbreakMarkup(std::vector< std::pair< wxString, int > > *aWords, const wxString &aText, const VECTOR2I &aSize, TEXT_STYLE_FLAGS aTextStyle) const
Definition: font.cpp:561
void Draw(KIGFX::GAL *aGal, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aCursor, const TEXT_ATTRIBUTES &aAttributes, const METRICS &aFontMetrics) const
Draw a string.
Definition: font.cpp:249
virtual bool IsOutline() const
Definition: font.h:139
VECTOR2I drawMarkup(BOX2I *aBoundingBox, std::vector< std::unique_ptr< GLYPH > > *aGlyphs, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aSize, const EDA_ANGLE &aAngle, bool aMirror, const VECTOR2I &aOrigin, TEXT_STYLE_FLAGS aTextStyle, const METRICS &aFontMetrics) const
Definition: font.cpp:375
VECTOR2I StringBoundaryLimits(const wxString &aText, const VECTOR2I &aSize, int aThickness, bool aBold, bool aItalic, const METRICS &aFontMetrics) const
Compute the boundary limits of aText (the bounding box of all shapes).
Definition: font.cpp:426
static std::map< std::tuple< wxString, bool, bool, bool >, FONT * > s_fontMap
Definition: font.h:296
virtual double GetInterline(double aGlyphHeight, const METRICS &aFontMetrics) const =0
Compute the distance (interline) between 2 lines of text (for multiline texts).
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.
static FONT * getDefaultFont()
Definition: font.cpp:137
void LinebreakText(wxString &aText, int aColumnWidth, const VECTOR2I &aGlyphSize, int aThickness, bool aBold, bool aItalic) const
Insert characters into text to ensure that no lines are wider than aColumnWidth.
Definition: font.cpp:571
double GetUnderlineVerticalPosition(double aGlyphHeight) const
Compute the vertical position of an underline.
Definition: font.h:109
double GetOverbarVerticalPosition(double aGlyphHeight) const
Compute the vertical position of an overbar.
Definition: font.h:100
static const METRICS & Default()
Definition: font.cpp:52
static OUTLINE_FONT * LoadFont(const wxString &aFontFileName, bool aBold, bool aItalic, const std::vector< wxString > *aEmbeddedFiles, bool aForDrawingSheet)
Load an outline font.
static STROKE_FONT * LoadFont(const wxString &aFontName)
Load a stroke font.
Definition: stroke_font.cpp:65
void AddPoint(const VECTOR2D &aPoint)
Definition: glyph.cpp:39
std::unique_ptr< GLYPH > Transform(const VECTOR2D &aGlyphSize, const VECTOR2I &aOffset, double aTilt, const EDA_ANGLE &aAngle, bool aMirror, const VECTOR2I &aOrigin)
Definition: glyph.cpp:74
Abstract interface for drawing on a 2D-surface.
virtual void SetLineWidth(float aLineWidth)
Set the line width.
virtual void DrawGlyphs(const std::vector< std::unique_ptr< KIFONT::GLYPH > > &aGlyphs)
Draw polygons representing font glyphs.
std::unique_ptr< NODE > Parse()
MARKUP_CACHE(size_t aMaxSize)
Definition: font.cpp:73
void Clear()
Definition: font.cpp:115
std::unordered_map< wxString, std::list< CACHE_ENTRY >::iterator > m_cache
Definition: font.cpp:124
ENTRY & Put(const CACHE_ENTRY::first_type &aQuery, ENTRY &&aResult)
Definition: font.cpp:78
std::pair< wxString, ENTRY > CACHE_ENTRY
Definition: font.cpp:71
std::list< CACHE_ENTRY > m_cacheMru
Definition: font.cpp:123
size_t m_maxSize
Definition: font.cpp:122
ENTRY * Get(const CACHE_ENTRY::first_type &aQuery)
Definition: font.cpp:103
GR_TEXT_H_ALIGN_T m_Halign
GR_TEXT_V_ALIGN_T m_Valign
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:401
METRICS g_defaultMetrics
Definition: font.cpp:49
static std::mutex s_markupCacheMutex
Definition: font.cpp:129
void wordbreakMarkup(std::vector< std::pair< wxString, int > > *aWords, const std::unique_ptr< MARKUP::NODE > &aNode, const KIFONT::FONT *aFont, const VECTOR2I &aSize, TEXT_STYLE_FLAGS aTextStyle)
Break marked-up text into "words".
Definition: font.cpp:478
static MARKUP_CACHE s_markupCache(1024)
VECTOR2I drawMarkup(BOX2I *aBoundingBox, std::vector< std::unique_ptr< GLYPH > > *aGlyphs, const MARKUP::NODE *aNode, const VECTOR2I &aPosition, const KIFONT::FONT *aFont, const VECTOR2I &aSize, const EDA_ANGLE &aAngle, bool aMirror, const VECTOR2I &aOrigin, TEXT_STYLE_FLAGS aTextStyle, const METRICS &aFontMetrics)
Definition: font.cpp:279
unsigned int TEXT_STYLE_FLAGS
Definition: font.h:64
#define KICAD_FONT_NAME
This file contains miscellaneous commonly used macros and functions.
CITER next(CITER it)
Definition: ptree.cpp:124
BOX2I boundingBox(T aObject, int aLayer)
Used by SHAPE_INDEX to get the bounding box of a generic T object.
Definition: shape_index.h:62
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:398
bool isOverbar() const
Definition: markup_parser.h:48
bool isSuperscript() const
Definition: markup_parser.h:50
wxString asWxString() const
bool isSubscript() const
Definition: markup_parser.h:49
std::unique_ptr< MARKUP::NODE > root
Definition: font.cpp:68
std::string source
Definition: font.cpp:67
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_H_ALIGN_INDETERMINATE
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_INDETERMINATE
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695