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 (C) 2021-2023 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
49FONT* FONT::s_defaultFont = nullptr;
50
51std::map< std::tuple<wxString, bool, bool>, FONT*> FONT::s_fontMap;
52
54{
55public:
56 struct ENTRY
57 {
58 std::string source;
59 std::unique_ptr<MARKUP::NODE> root;
60 };
61
62 typedef std::pair<wxString, ENTRY> CACHE_ENTRY;
63
64 MARKUP_CACHE( size_t aMaxSize ) :
65 m_maxSize( aMaxSize )
66 {
67 }
68
69 ENTRY& Put( const CACHE_ENTRY::first_type& aQuery, ENTRY&& aResult )
70 {
71 auto it = m_cache.find( aQuery );
72
73 m_cacheMru.emplace_front( CACHE_ENTRY( aQuery, std::move( aResult ) ) );
74
75 if( it != m_cache.end() )
76 {
77 m_cacheMru.erase( it->second );
78 m_cache.erase( it );
79 }
80
81 m_cache[aQuery] = m_cacheMru.begin();
82
83 if( m_cache.size() > m_maxSize )
84 {
85 auto last = m_cacheMru.end();
86 last--;
87 m_cache.erase( last->first );
88 m_cacheMru.pop_back();
89 }
90
91 return m_cacheMru.begin()->second;
92 }
93
94 ENTRY* Get( const CACHE_ENTRY::first_type& aQuery )
95 {
96 auto it = m_cache.find( aQuery );
97
98 if( it == m_cache.end() )
99 return nullptr;
100
101 m_cacheMru.splice( m_cacheMru.begin(), m_cacheMru, it->second );
102
103 return &m_cacheMru.begin()->second;
104 }
105
106 void Clear()
107 {
108 m_cacheMru.clear();
109 m_cache.clear();
110 }
111
112private:
113 size_t m_maxSize;
114 std::list<CACHE_ENTRY> m_cacheMru;
115 std::unordered_map<wxString, std::list<CACHE_ENTRY>::iterator> m_cache;
116};
117
118
120static std::mutex s_markupCacheMutex;
121
122
124{
125}
126
127
129{
130 if( !s_defaultFont )
131 s_defaultFont = STROKE_FONT::LoadFont( wxEmptyString );
132
133 return s_defaultFont;
134}
135
136
137FONT* FONT::GetFont( const wxString& aFontName, bool aBold, bool aItalic )
138{
139 if( aFontName.empty() || aFontName.StartsWith( KICAD_FONT_NAME ) )
140 return getDefaultFont();
141
142 std::tuple<wxString, bool, bool> key = { aFontName, aBold, aItalic };
143
144 FONT* font = s_fontMap[key];
145
146 if( !font )
147 font = OUTLINE_FONT::LoadFont( aFontName, aBold, aItalic );
148
149 if( !font )
150 font = getDefaultFont();
151
152 s_fontMap[key] = font;
153
154 return font;
155}
156
157
158bool FONT::IsStroke( const wxString& aFontName )
159{
160 // This would need a more complex implementation if we ever support more stroke fonts
161 // than the KiCad Font.
162 return aFontName == _( "Default Font" ) || aFontName == KICAD_FONT_NAME;
163}
164
165
166void FONT::getLinePositions( const wxString& aText, const VECTOR2I& aPosition,
167 wxArrayString& aTextLines, std::vector<VECTOR2I>& aPositions,
168 std::vector<VECTOR2I>& aExtents, const TEXT_ATTRIBUTES& aAttrs ) const
169{
170 wxStringSplit( aText, aTextLines, '\n' );
171 int lineCount = aTextLines.Count();
172 aPositions.reserve( lineCount );
173
174 int interline = GetInterline( aAttrs.m_Size.y, aAttrs.m_LineSpacing );
175 int height = 0;
176
177 for( int i = 0; i < lineCount; i++ )
178 {
179 VECTOR2I pos( aPosition.x, aPosition.y + i * interline );
180 VECTOR2I end = boundingBoxSingleLine( nullptr, aTextLines[i], pos, aAttrs.m_Size,
181 aAttrs.m_Italic );
182 VECTOR2I bBox( end - pos );
183
184 aExtents.push_back( bBox );
185
186 if( i == 0 )
187 height += ( aAttrs.m_Size.y * 1.17 ); // 1.17 is a fudge to match 6.0 positioning
188 else
189 height += interline;
190 }
191
192 VECTOR2I offset( 0, 0 );
193 offset.y += aAttrs.m_Size.y;
194
195 if( IsStroke() )
196 {
197 // Fudge factors to match 6.0 positioning
198 offset.x += aAttrs.m_StrokeWidth / 1.52;
199 offset.y -= aAttrs.m_StrokeWidth * 0.052;
200 }
201
202 switch( aAttrs.m_Valign )
203 {
204 case GR_TEXT_V_ALIGN_TOP: break;
205 case GR_TEXT_V_ALIGN_CENTER: offset.y -= height / 2; break;
206 case GR_TEXT_V_ALIGN_BOTTOM: offset.y -= height; break;
207 }
208
209 for( int i = 0; i < lineCount; i++ )
210 {
211 VECTOR2I lineSize = aExtents.at( i );
212 VECTOR2I lineOffset( offset );
213
214 lineOffset.y += i * interline;
215
216 switch( aAttrs.m_Halign )
217 {
218 case GR_TEXT_H_ALIGN_LEFT: break;
219 case GR_TEXT_H_ALIGN_CENTER: lineOffset.x = -lineSize.x / 2; break;
220 case GR_TEXT_H_ALIGN_RIGHT: lineOffset.x = -( lineSize.x + offset.x ); break;
221 }
222
223 aPositions.push_back( aPosition + lineOffset );
224 }
225}
226
227
238void FONT::Draw( KIGFX::GAL* aGal, const wxString& aText, const VECTOR2I& aPosition,
239 const VECTOR2I& aCursor, const TEXT_ATTRIBUTES& aAttrs ) const
240{
241 if( !aGal || aText.empty() )
242 return;
243
244 VECTOR2I position( aPosition - aCursor );
245
246 // Split multiline strings into separate ones and draw them line by line
247 wxArrayString strings_list;
248 std::vector<VECTOR2I> positions;
249 std::vector<VECTOR2I> extents;
250
251 getLinePositions( aText, position, strings_list, positions, extents, aAttrs );
252
253 aGal->SetLineWidth( aAttrs.m_StrokeWidth );
254
255 for( size_t i = 0; i < strings_list.GetCount(); i++ )
256 {
257 drawSingleLineText( aGal, nullptr, strings_list[i], positions[i], aAttrs.m_Size,
258 aAttrs.m_Angle, aAttrs.m_Mirrored, aPosition, aAttrs.m_Italic,
259 aAttrs.m_Underlined );
260 }
261}
262
263
267VECTOR2I drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
268 const MARKUP::NODE* aNode, const VECTOR2I& aPosition,
269 const KIFONT::FONT* aFont, const VECTOR2I& aSize, const EDA_ANGLE& aAngle,
270 bool aMirror, const VECTOR2I& aOrigin, TEXT_STYLE_FLAGS aTextStyle )
271{
272 VECTOR2I nextPosition = aPosition;
273 bool drawUnderline = false;
274 bool drawOverbar = false;
275
276 if( aNode )
277 {
278 TEXT_STYLE_FLAGS textStyle = aTextStyle;
279
280 if( !aNode->is_root() )
281 {
282 if( aNode->isSubscript() )
283 textStyle |= TEXT_STYLE::SUBSCRIPT;
284 else if( aNode->isSuperscript() )
285 textStyle |= TEXT_STYLE::SUPERSCRIPT;
286
287 if( aNode->isOverbar() )
288 drawOverbar = true;
289
290 if( aNode->has_content() )
291 {
292 BOX2I bbox;
293
294 nextPosition = aFont->GetTextAsGlyphs( &bbox, aGlyphs, aNode->asWxString(), aSize,
295 nextPosition, aAngle, aMirror, aOrigin,
296 textStyle );
297
298 if( aBoundingBox )
299 aBoundingBox->Merge( bbox );
300 }
301 }
302 else if( aTextStyle & TEXT_STYLE::UNDERLINE )
303 {
304 drawUnderline = true;
305 }
306
307 for( const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
308 {
309 nextPosition = drawMarkup( aBoundingBox, aGlyphs, child.get(), nextPosition, aFont,
310 aSize, aAngle, aMirror, aOrigin, textStyle );
311 }
312 }
313
314 if( drawUnderline )
315 {
316 // Shorten the bar a little so its rounded ends don't make it over-long
317 double barTrim = aSize.x * 0.1;
318 double barOffset = aFont->ComputeUnderlineVerticalPosition( aSize.y );
319
320 VECTOR2D barStart( aPosition.x + barTrim, aPosition.y - barOffset );
321 VECTOR2D barEnd( nextPosition.x - barTrim, nextPosition.y - barOffset );
322
323 if( aGlyphs )
324 {
325 STROKE_GLYPH barGlyph;
326
327 barGlyph.AddPoint( barStart );
328 barGlyph.AddPoint( barEnd );
329 barGlyph.Finalize();
330
331 aGlyphs->push_back( barGlyph.Transform( { 1.0, 1.0 }, { 0, 0 }, false, aAngle, aMirror,
332 aOrigin ) );
333 }
334 }
335
336 if( drawOverbar )
337 {
338 // Shorten the bar a little so its rounded ends don't make it over-long
339 double barTrim = aSize.x * 0.1;
340 double barOffset = aFont->ComputeOverbarVerticalPosition( aSize.y );
341
342 VECTOR2D barStart( aPosition.x + barTrim, aPosition.y - barOffset );
343 VECTOR2D barEnd( nextPosition.x - barTrim, nextPosition.y - barOffset );
344
345 if( aGlyphs )
346 {
347 STROKE_GLYPH barGlyph;
348
349 barGlyph.AddPoint( barStart );
350 barGlyph.AddPoint( barEnd );
351 barGlyph.Finalize();
352
353 aGlyphs->push_back( barGlyph.Transform( { 1.0, 1.0 }, { 0, 0 }, false, aAngle, aMirror,
354 aOrigin ) );
355 }
356 }
357
358 return nextPosition;
359}
360
361
362VECTOR2I FONT::drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
363 const wxString& aText, const VECTOR2I& aPosition, const VECTOR2I& aSize,
364 const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
365 TEXT_STYLE_FLAGS aTextStyle ) const
366{
367 std::lock_guard<std::mutex> lock( s_markupCacheMutex );
368
369 MARKUP_CACHE::ENTRY* markup = s_markupCache.Get( aText );
370
371 if( !markup || !markup->root )
372 {
373 MARKUP_CACHE::ENTRY& cached = s_markupCache.Put( aText, {} );
374
375 cached.source = TO_UTF8( aText );
376 MARKUP::MARKUP_PARSER markupParser( &cached.source );
377 cached.root = markupParser.Parse();
378 markup = &cached;
379 }
380
381 wxASSERT( markup && markup->root );
382
383 return ::drawMarkup( aBoundingBox, aGlyphs, markup->root.get(), aPosition, this, aSize, aAngle,
384 aMirror, aOrigin, aTextStyle );
385}
386
387
388void FONT::drawSingleLineText( KIGFX::GAL* aGal, BOX2I* aBoundingBox, const wxString& aText,
389 const VECTOR2I& aPosition, const VECTOR2I& aSize,
390 const EDA_ANGLE& aAngle, bool aMirror, const VECTOR2I& aOrigin,
391 bool aItalic, bool aUnderline ) const
392{
393 if( !aGal )
394 return;
395
396 TEXT_STYLE_FLAGS textStyle = 0;
397
398 if( aItalic )
399 textStyle |= TEXT_STYLE::ITALIC;
400
401 if( aUnderline )
402 textStyle |= TEXT_STYLE::UNDERLINE;
403
404 std::vector<std::unique_ptr<GLYPH>> glyphs;
405
406 (void) drawMarkup( aBoundingBox, &glyphs, aText, aPosition, aSize, aAngle, aMirror, aOrigin,
407 textStyle );
408
409 aGal->DrawGlyphs( glyphs );
410}
411
412
413VECTOR2I FONT::StringBoundaryLimits( const wxString& aText, const VECTOR2I& aSize, int aThickness,
414 bool aBold, bool aItalic ) const
415{
416 // TODO do we need to parse every time - have we already parsed?
418 TEXT_STYLE_FLAGS textStyle = 0;
419
420 if( aBold )
421 textStyle |= TEXT_STYLE::BOLD;
422
423 if( aItalic )
424 textStyle |= TEXT_STYLE::ITALIC;
425
426 (void) drawMarkup( &boundingBox, nullptr, aText, VECTOR2I(), aSize, ANGLE_0, false, VECTOR2I(),
427 textStyle );
428
429 if( IsStroke() )
430 {
431 // Inflate by a bit more than thickness/2 to catch diacriticals, descenders, etc.
432 boundingBox.Inflate( KiROUND( aThickness * 1.5 ) );
433 }
434 else if( IsOutline() )
435 {
436 // Outline fonts have thickness built in, and *usually* stay within their ascent/descent
437 }
438
439 return boundingBox.GetSize();
440}
441
442
443VECTOR2I FONT::boundingBoxSingleLine( BOX2I* aBBox, const wxString& aText,
444 const VECTOR2I& aPosition, const VECTOR2I& aSize,
445 bool aItalic ) const
446{
447 TEXT_STYLE_FLAGS textStyle = 0;
448
449 if( aItalic )
450 textStyle |= TEXT_STYLE::ITALIC;
451
452 VECTOR2I extents = drawMarkup( aBBox, nullptr, aText, aPosition, aSize, ANGLE_0, false,
453 VECTOR2I(), textStyle );
454
455 return extents;
456}
457
458
459/*
460 * Break marked-up text into "words". In this context, a "word" is EITHER a run of marked-up
461 * text (subscript, superscript or overbar), OR a run of non-marked-up text separated by spaces.
462 */
463void wordbreakMarkup( std::vector<std::pair<wxString, int>>* aWords,
464 const std::unique_ptr<MARKUP::NODE>& aNode, const KIFONT::FONT* aFont,
465 const VECTOR2I& aSize, TEXT_STYLE_FLAGS aTextStyle )
466{
467 TEXT_STYLE_FLAGS textStyle = aTextStyle;
468
469 if( !aNode->is_root() )
470 {
471 wxChar escapeChar = 0;
472
473 if( aNode->isSubscript() )
474 {
475 escapeChar = '_';
476 textStyle = TEXT_STYLE::SUBSCRIPT;
477 }
478 else if( aNode->isSuperscript() )
479 {
480 escapeChar = '^';
481 textStyle = TEXT_STYLE::SUPERSCRIPT;
482 }
483
484 if( aNode->isOverbar() )
485 {
486 escapeChar = '~';
487 textStyle |= TEXT_STYLE::OVERBAR;
488 }
489
490 if( escapeChar )
491 {
492 wxString word = wxString::Format( wxT( "%c{" ), escapeChar );
493 int width = 0;
494
495 if( aNode->has_content() )
496 {
497 VECTOR2I next = aFont->GetTextAsGlyphs( nullptr, nullptr, aNode->asWxString(),
498 aSize, { 0, 0 }, ANGLE_0, false, { 0, 0 },
499 textStyle );
500 word += aNode->asWxString();
501 width += next.x;
502 }
503
504 std::vector<std::pair<wxString, int>> childWords;
505
506 for( const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
507 wordbreakMarkup( &childWords, child, aFont, aSize, textStyle );
508
509 for( const std::pair<wxString, int>& childWord : childWords )
510 {
511 word += childWord.first;
512 width += childWord.second;
513 }
514
515 word += wxT( "}" );
516 aWords->emplace_back( std::make_pair( word, width ) );
517 return;
518 }
519 else
520 {
521 wxString textRun = aNode->asWxString();
522 wxStringTokenizer tokenizer( textRun, " ", wxTOKEN_RET_DELIMS );
523 std::vector<wxString> words;
524
525 while( tokenizer.HasMoreTokens() )
526 words.emplace_back( tokenizer.GetNextToken() );
527
528 for( const wxString& word : words )
529 {
530 wxString chars = word;
531 chars.Trim();
532
533 int w = aFont->GetTextAsGlyphs( nullptr, nullptr, chars, aSize, { 0, 0 },
534 ANGLE_0, false, { 0, 0 }, textStyle ).x;
535
536 aWords->emplace_back( std::make_pair( word, w ) );
537 }
538 }
539 }
540
541 for( const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
542 wordbreakMarkup( aWords, child, aFont, aSize, textStyle );
543}
544
545
546void FONT::wordbreakMarkup( std::vector<std::pair<wxString, int>>* aWords, const wxString& aText,
547 const VECTOR2I& aSize, TEXT_STYLE_FLAGS aTextStyle ) const
548{
549 MARKUP::MARKUP_PARSER markupParser( TO_UTF8( aText ) );
550 std::unique_ptr<MARKUP::NODE> root = markupParser.Parse();
551
552 ::wordbreakMarkup( aWords, root, this, aSize, aTextStyle );
553}
554
555
556/*
557 * This is a highly simplified line-breaker. KiCad is an EDA tool, not a word processor.
558 *
559 * 1) It breaks only on spaces. If you type a word wider than the column width then you get
560 * overflow.
561 * 2) It treats runs of formatted text (superscript, subscript, overbar) as single words.
562 * 3) It does not perform justification.
563 *
564 * The results of the linebreaking are the addition of \n in the text. It is presumed that this
565 * function is called on m_shownText (or equivalent) rather than the original source text.
566 */
567void FONT::LinebreakText( wxString& aText, int aColumnWidth, const VECTOR2I& aSize, int aThickness,
568 bool aBold, bool aItalic ) const
569{
570 TEXT_STYLE_FLAGS textStyle = 0;
571
572 if( aBold )
573 textStyle |= TEXT_STYLE::BOLD;
574
575 if( aItalic )
576 textStyle |= TEXT_STYLE::ITALIC;
577
578 int spaceWidth = GetTextAsGlyphs( nullptr, nullptr, wxS( " " ), aSize, VECTOR2I(), ANGLE_0,
579 false, VECTOR2I(), textStyle ).x;
580
581 wxArrayString textLines;
582 wxStringSplit( aText, textLines, '\n' );
583
584 aText = wxEmptyString;
585
586 for( size_t ii = 0; ii < textLines.Count(); ++ii )
587 {
588 std::vector<std::pair<wxString, int>> markup;
589 std::vector<std::pair<wxString, int>> words;
590
591 wordbreakMarkup( &markup, textLines[ii], aSize, textStyle );
592
593 for( const auto& [ run, runWidth ] : markup )
594 {
595 if( !words.empty() && !words.back().first.EndsWith( ' ' ) )
596 {
597 words.back().first += run;
598 words.back().second += runWidth;
599 }
600 else
601 {
602 words.emplace_back( std::make_pair( run, runWidth ) );
603 }
604 }
605
606 bool buryMode = false;
607 int lineWidth = 0;
608 wxString pendingSpaces;
609
610 for( const auto& [ word, wordWidth ] : words )
611 {
612 int pendingSpaceWidth = (int) pendingSpaces.Length() * spaceWidth;
613 bool overflow = lineWidth + pendingSpaceWidth + wordWidth > aColumnWidth - aThickness;
614
615 if( overflow && pendingSpaces.Length() > 0 )
616 {
617 aText += '\n';
618 lineWidth = 0;
619 pendingSpaces = wxEmptyString;
620 pendingSpaceWidth = 0;
621 buryMode = true;
622 }
623
624 if( word == wxS( " " ) )
625 {
626 pendingSpaces += word;
627 }
628 else
629 {
630 if( buryMode )
631 {
632 buryMode = false;
633 }
634 else
635 {
636 aText += pendingSpaces;
637 lineWidth += pendingSpaceWidth;
638 }
639
640 if( word.EndsWith( ' ' ) )
641 {
642 aText += word.Left( word.Length() - 1 );
643 pendingSpaces = wxS( " " );
644 }
645 else
646 {
647 aText += word;
648 pendingSpaces = wxEmptyString;
649 }
650
651 lineWidth += wordWidth;
652 }
653 }
654
655 // Add the newlines back onto the string
656 if( ii != ( textLines.Count() - 1 ) )
657 aText += '\n';
658 }
659}
660
661
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
const Vec & GetSize() const
Definition: box2.h:179
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:588
FONT is an abstract base class for both outline and stroke fonts.
Definition: font.h:105
virtual double ComputeUnderlineVerticalPosition(double aGlyphHeight) const =0
Compute the vertical position of an underline.
virtual double GetInterline(double aGlyphHeight, double aLineSpacing=1.0) const =0
Compute the distance (interline) between 2 lines of text (for multiline texts).
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false)
Definition: font.cpp:137
void Draw(KIGFX::GAL *aGal, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aCursor, const TEXT_ATTRIBUTES &aAttrs) const
Draw a string.
Definition: font.cpp:238
virtual double ComputeOverbarVerticalPosition(double aGlyphHeight) const =0
Compute the vertical position of an overbar.
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
Draws a single line of text.
Definition: font.cpp:388
virtual bool IsStroke() const
Definition: font.h:112
static FONT * s_defaultFont
Definition: font.h:266
void getLinePositions(const wxString &aText, const VECTOR2I &aPosition, wxArrayString &aTextLines, std::vector< VECTOR2I > &aPositions, std::vector< VECTOR2I > &aExtents, const TEXT_ATTRIBUTES &aAttrs) const
Definition: font.cpp:166
VECTOR2I boundingBoxSingleLine(BOX2I *aBBox, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aSize, bool aItalic) const
Computes the bounding box for a single line of text.
Definition: font.cpp:443
void wordbreakMarkup(std::vector< std::pair< wxString, int > > *aWords, const wxString &aText, const VECTOR2I &aSize, TEXT_STYLE_FLAGS aTextStyle) const
Factor that determines the pitch between 2 lines.
Definition: font.cpp:546
virtual bool IsOutline() const
Definition: font.h:113
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
Definition: font.cpp:362
static std::map< std::tuple< wxString, bool, bool >, FONT * > s_fontMap
Definition: font.h:268
VECTOR2I StringBoundaryLimits(const wxString &aText, const VECTOR2I &aSize, int aThickness, bool aBold, bool aItalic) const
Compute the boundary limits of aText (the bounding box of all shapes).
Definition: font.cpp:413
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:128
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:567
static OUTLINE_FONT * LoadFont(const wxString &aFontFileName, bool aBold, bool aItalic)
Load an outline font.
static STROKE_FONT * LoadFont(const wxString &aFontName)
Load a stroke font.
Definition: stroke_font.cpp:73
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:64
void Clear()
Definition: font.cpp:106
std::unordered_map< wxString, std::list< CACHE_ENTRY >::iterator > m_cache
Definition: font.cpp:115
ENTRY & Put(const CACHE_ENTRY::first_type &aQuery, ENTRY &&aResult)
Definition: font.cpp:69
std::pair< wxString, ENTRY > CACHE_ENTRY
Definition: font.cpp:62
std::list< CACHE_ENTRY > m_cacheMru
Definition: font.cpp:114
size_t m_maxSize
Definition: font.cpp:113
ENTRY * Get(const CACHE_ENTRY::first_type &aQuery)
Definition: font.cpp:94
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:429
static std::mutex s_markupCacheMutex
Definition: font.cpp:120
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)
Definition: font.cpp:463
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)
Definition: font.cpp:267
unsigned int TEXT_STYLE_FLAGS
Definition: font.h:63
#define KICAD_FONT_NAME
This file contains miscellaneous commonly used macros and functions.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
Definition: font.h:100
CITER next(CITER it)
Definition: ptree.cpp:126
BOX2I boundingBox(T aObject)
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.
bool isOverbar() const
Definition: markup_parser.h:47
bool isSuperscript() const
Definition: markup_parser.h:49
wxString asWxString() const
bool isSubscript() const
Definition: markup_parser.h:48
std::unique_ptr< MARKUP::NODE > root
Definition: font.cpp:59
std::string source
Definition: font.cpp:58
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588