29#include <unordered_map> 
   41#include <wx/tokenzr.h> 
   68        std::unique_ptr<MARKUP::NODE> 
root;
 
 
   78        auto it = 
m_cache.find( aQuery );
 
   80        m_cacheMru.emplace_front( std::make_pair( aQuery, std::move( aResult ) ) );
 
 
  103        auto it = 
m_cache.find( aQuery );
 
 
  122    std::unordered_map<wxString, std::list<std::pair<wxString, ENTRY>>::iterator> 
m_cache;
 
 
  148                     const std::vector<wxString>* aEmbeddedFiles, 
bool aForDrawingSheet )
 
  153    std::tuple<wxString, bool, bool, bool> key = { aFontName, aBold, aItalic, aForDrawingSheet };
 
  155    FONT* font = 
nullptr;
 
 
  182                             wxArrayString& aTextLines, std::vector<VECTOR2I>& aPositions,
 
  184                             const METRICS& aFontMetrics )
 const 
  187    int lineCount = aTextLines.Count();
 
  188    aPositions.reserve( lineCount );
 
  193    for( 
int i = 0; i < lineCount; i++ )
 
  195        VECTOR2I pos( aPosition.
x, aPosition.
y + i * interline );
 
  200        aExtents.push_back( bBox );
 
  203            height += ( aAttrs.
m_Size.
y * 1.17 );   
 
  224        wxFAIL_MSG( wxT( 
"Indeterminate state legal only in dialogs." ) );
 
  228    for( 
int i = 0; i < lineCount; i++ )
 
  230        VECTOR2I lineSize = aExtents.at( i );
 
  233        lineOffset.
y += i * interline;
 
  241            wxFAIL_MSG( wxT( 
"Indeterminate state legal only in dialogs." ) );
 
  245        aPositions.push_back( aPosition + lineOffset );
 
 
  252                 const METRICS& aFontMetrics )
 const 
  254    if( !aGal || aText.empty() )
 
  257    VECTOR2I  position( aPosition - aCursor );
 
  260    wxArrayString         strings_list;
 
  261    std::vector<VECTOR2I> positions;
 
  262    std::vector<VECTOR2I> extents;
 
  264    getLinePositions( aText, position, strings_list, positions, extents, aAttrs, aFontMetrics );
 
  268    for( 
size_t i = 0; i < strings_list.GetCount(); i++ )
 
 
  287    bool     drawUnderline = 
false;
 
  288    bool     drawOverbar = 
false;
 
  294        if( !aNode->is_root() )
 
  304            if( aNode->has_content() )
 
  309                                                       nextPosition, aAngle, aMirror, aOrigin,
 
  313                    aBoundingBox->
Merge( bbox );
 
  318            drawUnderline = 
true;
 
  321        for( 
const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
 
  323            nextPosition = 
drawMarkup( aBoundingBox, aGlyphs, child.get(), nextPosition, aFont,
 
  324                                       aSize, aAngle, aMirror, aOrigin, textStyle, aFontMetrics );
 
  331        double barTrim = aSize.
x * 0.1;
 
  334        VECTOR2D barStart( aPosition.
x + barTrim, aPosition.
y - barOffset );
 
  335        VECTOR2D barEnd( nextPosition.
x - barTrim, nextPosition.
y - barOffset );
 
  345            aGlyphs->push_back( barGlyph.
Transform( { 1.0, 1.0 }, { 0, 0 }, 
false, aAngle, aMirror,
 
  353        double barTrim = aSize.
x * 0.1;
 
  356        VECTOR2D barStart( aPosition.
x + barTrim, aPosition.
y - barOffset );
 
  357        VECTOR2D barEnd( nextPosition.
x - barTrim, nextPosition.
y - barOffset );
 
  367            aGlyphs->push_back( barGlyph.
Transform( { 1.0, 1.0 }, { 0, 0 }, 
false, aAngle, aMirror,
 
 
  385    if( !markup || !markup->
root )
 
  395    wxASSERT( markup && markup->
root );
 
  397    return ::drawMarkup( aBoundingBox, aGlyphs, markup->
root.get(), aPosition, 
this, aSize, aAngle,
 
  398                         aMirror, aOrigin, aTextStyle, aFontMetrics );
 
 
  405                               bool aItalic, 
bool aUnderline, 
const METRICS& aFontMetrics )
 const 
  418    std::vector<std::unique_ptr<GLYPH>> glyphs;
 
  420    (void) 
drawMarkup( aBoundingBox, &glyphs, aText, aPosition, aSize, aAngle, aMirror, aOrigin,
 
  421                       textStyle, aFontMetrics );
 
 
  428                                     bool aBold, 
bool aItalic, 
const METRICS& aFontMetrics )
 const 
  441                       textStyle, aFontMetrics );
 
 
  459                                      bool aItalic, 
const METRICS& aFontMetrics )
 const 
  467                                   VECTOR2I(), textStyle, aFontMetrics );
 
 
  480                      const std::unique_ptr<MARKUP::NODE>& aNode, 
const KIFONT::FONT* aFont,
 
  485    if( !aNode->is_root() )
 
  487        wxChar escapeChar = 0;
 
  489        if( aNode->isSubscript() )
 
  494        else if( aNode->isSuperscript() )
 
  500        if( aNode->isOverbar() )
 
  508            wxString word = wxString::Format( wxT( 
"%c{" ), escapeChar );
 
  511            if( aNode->has_content() )
 
  514                                                        aSize, { 0, 0 }, 
ANGLE_0, 
false, { 0, 0 },
 
  516                word += aNode->asWxString();
 
  520            std::vector<std::pair<wxString, int>> childWords;
 
  522            for( 
const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
 
  525            for( 
const std::pair<wxString, int>& childWord : childWords )
 
  527                word += childWord.first;
 
  528                width += childWord.second;
 
  532            aWords->emplace_back( std::make_pair( word, width ) );
 
  537            wxString              textRun = aNode->asWxString();
 
  538            wxStringTokenizer     tokenizer( textRun, 
" ", wxTOKEN_RET_DELIMS );
 
  539            std::vector<wxString> words;
 
  541            while( tokenizer.HasMoreTokens() )
 
  542                words.emplace_back( tokenizer.GetNextToken() );
 
  544            for( 
const wxString& word : words )
 
  546                wxString chars = word;
 
  549                int w = aFont->
GetTextAsGlyphs( 
nullptr, 
nullptr, chars, aSize, { 0, 0 },
 
  550                                                ANGLE_0, 
false, { 0, 0 }, textStyle ).x;
 
  552                aWords->emplace_back( std::make_pair( word, w ) );
 
  557    for( 
const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
 
 
  566    std::unique_ptr<MARKUP::NODE> root = markupParser.
Parse();
 
 
  573                          bool aBold, 
bool aItalic )
 const 
  586    wxArrayString  textLines;
 
  589    aText = wxEmptyString;
 
  591    for( 
size_t ii = 0; ii < textLines.Count(); ++ii )
 
  593        std::vector<std::pair<wxString, int>> markup;
 
  594        std::vector<std::pair<wxString, int>> words;
 
  598        for( 
const auto& [ run, runWidth ] : markup )
 
  600            if( !words.empty() && !words.back().first.EndsWith( 
' ' ) )
 
  602                words.back().first += run;
 
  603                words.back().second += runWidth;
 
  607                words.emplace_back( std::make_pair( run, runWidth ) );
 
  611        bool     buryMode = 
false;
 
  613        wxString pendingSpaces;
 
  615        for( 
const auto& [ word, wordWidth ] : words )
 
  617            int  pendingSpaceWidth = (int) pendingSpaces.Length() * spaceWidth;
 
  618            bool overflow = lineWidth + pendingSpaceWidth + wordWidth > aColumnWidth - aThickness;
 
  620            if( overflow && pendingSpaces.Length() > 0 )
 
  624                pendingSpaces = wxEmptyString;
 
  625                pendingSpaceWidth = 0;
 
  629            if( word == wxS( 
" " ) )
 
  631                pendingSpaces += word;
 
  641                    aText += pendingSpaces;
 
  642                    lineWidth += pendingSpaceWidth;
 
  645                if( word.EndsWith( 
' ' ) )
 
  647                    aText += word.Left( word.Length() - 1 );
 
  648                    pendingSpaces = wxS( 
" " );
 
  653                    pendingSpaces = wxEmptyString;
 
  656                lineWidth += wordWidth;
 
  661        if( ii != ( textLines.Count() - 1 ) )
 
 
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
 
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
 
FONT is an abstract base class for both outline and stroke fonts.
 
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.
 
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
 
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.
 
virtual bool IsStroke() const
 
static FONT * s_defaultFont
 
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
 
void wordbreakMarkup(std::vector< std::pair< wxString, int > > *aWords, const wxString &aText, const VECTOR2I &aSize, TEXT_STYLE_FLAGS aTextStyle) const
 
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.
 
virtual bool IsOutline() const
 
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
 
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).
 
static std::map< std::tuple< wxString, bool, bool, bool >, FONT * > s_fontMap
 
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()
 
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.
 
double GetUnderlineVerticalPosition(double aGlyphHeight) const
Compute the vertical position of an underline.
 
double GetOverbarVerticalPosition(double aGlyphHeight) const
Compute the vertical position of an overbar.
 
static const METRICS & Default()
 
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.
 
void AddPoint(const VECTOR2D &aPoint)
 
std::unique_ptr< GLYPH > Transform(const VECTOR2D &aGlyphSize, const VECTOR2I &aOffset, double aTilt, const EDA_ANGLE &aAngle, bool aMirror, const VECTOR2I &aOrigin)
 
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()
 
std::list< std::pair< wxString, ENTRY > > m_cacheMru
 
MARKUP_CACHE(size_t aMaxSize)
 
ENTRY & Put(const wxString &aQuery, ENTRY &&aResult)
 
ENTRY * Get(const wxString &aQuery)
 
std::unordered_map< wxString, std::list< std::pair< wxString, ENTRY > >::iterator > m_cache
 
GR_TEXT_H_ALIGN_T m_Halign
 
GR_TEXT_V_ALIGN_T m_Valign
 
static constexpr EDA_ANGLE ANGLE_0
 
static std::mutex s_markupCacheMutex
 
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".
 
static std::mutex s_defaultFontMutex
 
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)
 
unsigned int TEXT_STYLE_FLAGS
 
This file contains miscellaneous commonly used macros and functions.
 
BOX2I boundingBox(T aObject, int aLayer)
Used by SHAPE_INDEX to get the bounding box of a generic T object.
 
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.
 
bool isSuperscript() const
 
wxString asWxString() const
 
std::unique_ptr< MARKUP::NODE > root
 
@ GR_TEXT_H_ALIGN_INDETERMINATE
 
@ GR_TEXT_V_ALIGN_INDETERMINATE
 
VECTOR2< int32_t > VECTOR2I
 
VECTOR2< double > VECTOR2D