30#include <fmt/format.h> 
   37static constexpr int MAX_SIMPLE_FONT_CODES = 256;
 
   45                                     bool aInvertY, 
bool aBold )
 
   50    fmt::memory_buffer buffer;
 
   56        if( boldMul < 1.0 ) boldMul = 1.0;
 
   63    double lw = aUnitsPerEm * factor;
 
   64    fmt::format_to( std::back_inserter( buffer ), 
"{:.3f} w 1 J 1 j ", lw );
 
   67    for( 
const std::vector<VECTOR2D>& stroke : *aGlyph )
 
   69        bool firstPoint = 
true;
 
   71        for( 
const VECTOR2D& point : stroke )
 
   73            double x = ( point.x + cfg.m_PDFStrokeFontXOffset ) * aUnitsPerEm;
 
   74            double y = point.y * aUnitsPerEm;
 
   79                y += cfg.m_PDFStrokeFontYOffset * aUnitsPerEm;
 
   84                fmt::format_to( std::back_inserter( buffer ), 
"{:.3f} {:.3f} m ", x, y );
 
   89                fmt::format_to( std::back_inserter( buffer ), 
"{:.3f} {:.3f} l ", x, y );
 
   94            fmt::format_to( std::back_inserter( buffer ), 
"S " );
 
   97    return std::string( buffer.data(), buffer.size() );
 
  100static std::string formatUnicodeHex( uint32_t aCodepoint )
 
  102    if( aCodepoint <= 0xFFFF )
 
  103        return fmt::format( 
"{:04X}", aCodepoint );
 
  105    if( aCodepoint <= 0x10FFFF )
 
  107        uint32_t value = aCodepoint - 0x10000;
 
  108        uint16_t high = 0xD800 + ( value >> 10 );
 
  109        uint16_t low = 0xDC00 + ( value & 0x3FF );
 
  110        return fmt::format( 
"{:04X}{:04X}", high, low );
 
  113    return std::string( 
"003F" );
 
  119                                                unsigned aSubsetIndex, 
bool aBold, 
bool aItalic ) :
 
  123        m_cmapName( fmt::format( 
"KiCadStrokeCMap{}", aSubsetIndex ) ),
 
  124        m_widths( MAX_SIMPLE_FONT_CODES, 0.0 ),
 
  141    notdef.
m_name = 
".notdef";
 
 
  191        glyph = 
m_font->GetGlyph( glyphIndex );
 
  192        bbox = 
m_font->GetGlyphBoundingBox( glyphIndex );
 
  210        double newMinY = -data.
m_maxY;
 
  211        double newMaxY = -data.
m_minY;
 
  224    if( kerningFactor <= 0.0 )
 
  229    data.
m_stream = fmt::format( 
"{:.3f} 0 {:.3f} {:.3f} {:.3f} {:.3f} d1 {}",
 
  241    m_glyphs.push_back( std::move( data ) );
 
 
  267    return static_cast<int>( 
m_glyphs.size() );
 
 
  288    fmt::memory_buffer buffer;
 
  289    fmt::format_to( std::back_inserter( buffer ), 
"[ {} ", first );
 
  291    for( 
int code = first; code <= last; ++code )
 
  296        fmt::format_to( std::back_inserter( buffer ), 
"/{} ", glyph->
m_name );
 
  298        fmt::format_to( std::back_inserter( buffer ), 
"/.notdef " );
 
  301    fmt::format_to( std::back_inserter( buffer ), 
"]" );
 
  302    return std::string( buffer.data(), buffer.size() );
 
 
  311    fmt::memory_buffer buffer;
 
  312    fmt::format_to( std::back_inserter( buffer ), 
"[" );
 
  314    for( 
int code = first; code <= last; ++code )
 
  315        fmt::format_to( std::back_inserter( buffer ), 
" {:g}", 
m_widths[code] );
 
  317    fmt::format_to( std::back_inserter( buffer ), 
" ]" );
 
  318    return std::string( buffer.data(), buffer.size() );
 
 
  324    size_t mappingCount = 0;
 
  328        if( glyph.m_code == 0 )
 
  334    fmt::memory_buffer buffer;
 
  336    fmt::format_to( std::back_inserter( buffer ), 
"/CIDInit /ProcSet findresource begin\n" );
 
  337    fmt::format_to( std::back_inserter( buffer ), 
"12 dict begin\n" );
 
  338    fmt::format_to( std::back_inserter( buffer ), 
"begincmap\n" );
 
  339    fmt::format_to( std::back_inserter( buffer ), 
"/CIDSystemInfo << /Registry (KiCad) /Ordering (StrokeFont) /Supplement 0 >> def\n" );
 
  340    fmt::format_to( std::back_inserter( buffer ), 
"/CMapName /{} def\n", 
m_cmapName );
 
  341    fmt::format_to( std::back_inserter( buffer ), 
"/CMapType 2 def\n" );
 
  342    fmt::format_to( std::back_inserter( buffer ), 
"1 begincodespacerange\n" );
 
  343    fmt::format_to( std::back_inserter( buffer ), 
"<00> <FF>\n" );
 
  344    fmt::format_to( std::back_inserter( buffer ), 
"endcodespacerange\n" );
 
  346    fmt::format_to( std::back_inserter( buffer ), 
"{} beginbfchar\n", mappingCount );
 
  350        if( glyph.m_code == 0 )
 
  353        fmt::format_to( std::back_inserter( buffer ), 
"<{:02X}> <{}>\n", glyph.m_code,
 
  354                        formatUnicodeHex( 
static_cast<uint32_t
>( glyph.m_unicode ) ) );
 
  357    fmt::format_to( std::back_inserter( buffer ), 
"endbfchar\n" );
 
  358    fmt::format_to( std::back_inserter( buffer ), 
"endcmap\n" );
 
  359    fmt::format_to( std::back_inserter( buffer ), 
"CMapName currentdict /CMap defineresource pop\n" );
 
  360    fmt::format_to( std::back_inserter( buffer ), 
"end\n" );
 
  361    fmt::format_to( std::back_inserter( buffer ), 
"end\n" );
 
  363    return std::string( buffer.data(), buffer.size() );
 
 
  369    int value = 
static_cast<int>( aCode );
 
  372        return static_cast<int>( 
'?' ) - 
' ';
 
  374    int index = value - 
' ';
 
  375    int count = 
static_cast<int>( 
m_font ? 
m_font->GetGlyphCount() : 0 );
 
  377    if( index < 0 || index >= count )
 
  378        return static_cast<int>( 
'?' ) - 
' ';
 
 
  386    return fmt::format( 
"g{:02X}", aCode );
 
 
  394        if( glyph.m_code == aCode )
 
 
  403        m_font( 
KIFONT::STROKE_FONT::LoadFont( wxEmptyString ) ),
 
 
  423    unsigned key = 
styleKey( aBold, aItalic );
 
 
  428                                            std::vector<PDF_STROKE_FONT_RUN>* aRuns,
 
  429                                            bool aBold, 
bool aItalic )
 
  440    std::string currentBytes;
 
  442    for( wxUniChar ch : aText )
 
  454        if( subset != currentSubset )
 
  456            if( !currentBytes.empty() && currentSubset )
 
  457                aRuns->push_back( { currentSubset, currentBytes, aBold, aItalic } );
 
  459            currentSubset = subset;
 
  460            currentBytes.clear();
 
  463        currentBytes.push_back( 
static_cast<char>( code ) );
 
  466    if( !currentBytes.empty() && currentSubset )
 
  467        aRuns->push_back( { currentSubset, std::move( currentBytes ), aBold, aItalic } );
 
 
  474    for( 
const std::unique_ptr<PDF_STROKE_FONT_SUBSET>& subset : 
group.subsets )
 
  476        if( subset->Contains( aCode ) )
 
  480    for( 
const std::unique_ptr<PDF_STROKE_FONT_SUBSET>& subset : 
group.subsets )
 
  482        if( subset->IsFull() )
 
  485        if( subset->EnsureGlyph( aCode ) >= 0 )
 
  490    auto newSubset = std::make_unique<PDF_STROKE_FONT_SUBSET>( 
m_font.get(), 
m_unitsPerEm, subsetIndex, aBold, aItalic );
 
  493    group.subsets.emplace_back( std::move( newSubset ) );
 
 
  499    std::vector<PDF_STROKE_FONT_SUBSET*> out;
 
  504        for( 
const auto& 
up : 
group.subsets )
 
  505            out.push_back( 
up.get() );
 
 
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
 
constexpr const Vec & GetOrigin() const
 
constexpr const SizeVec & GetSize() const
 
Implement a stroke font drawing.
 
static STROKE_FONT * LoadFont(const wxString &aFontName)
Load a stroke font.
 
std::unique_ptr< KIFONT::STROKE_FONT > m_font
 
std::map< unsigned, STYLE_GROUP > m_styleGroups
 
unsigned m_nextSubsetIndex
 
STYLE_GROUP & groupFor(bool aBold, bool aItalic)
 
PDF_STROKE_FONT_SUBSET * ensureSubsetForGlyph(wxUniChar aCode, bool aBold, bool aItalic)
 
std::vector< PDF_STROKE_FONT_SUBSET * > AllSubsets() const
 
void EncodeString(const wxString &aText, std::vector< PDF_STROKE_FONT_RUN > *aRuns, bool aBold=false, bool aItalic=false)
 
PDF_STROKE_FONT_MANAGER()
 
static unsigned styleKey(bool aBold, bool aItalic)
 
std::string BuildDifferencesArray() const
 
std::string m_resourceName
 
const KIFONT::STROKE_FONT * m_font
 
int EnsureGlyph(wxUniChar aCode)
 
int CodeForGlyph(wxUniChar aCode) const
 
std::string BuildWidthsArray() const
 
std::map< wxUniChar, int > m_unicodeToCode
 
std::string makeGlyphName(int aCode) const
 
std::vector< double > m_widths
 
std::string BuildToUnicodeCMap() const
 
bool Contains(wxUniChar aCode) const
 
std::vector< GLYPH > m_glyphs
 
const GLYPH * glyphForCode(int aCode) const
 
PDF_STROKE_FONT_SUBSET(const KIFONT::STROKE_FONT *aFont, double aUnitsPerEm, unsigned aSubsetIndex, bool aBold, bool aItalic)
 
int glyphIndexForUnicode(wxUniChar aCode) const
 
double m_PDFStrokeFontKerningFactor
Kerning (spacing) factor applied to glyph advance (width).
 
double m_PDFStrokeFontYOffset
Vertical offset factor applied to stroke font glyph coordinates (in EM units) after Y inversion to co...
 
double m_PDFStrokeFontBoldMultiplier
Multiplier applied to stroke width factor when rendering bold stroke font subsets.
 
double m_PDFStrokeFontWidthFactor
Stroke font line width factor relative to EM size for PDF stroke fonts.
 
VECTOR2< double > VECTOR2D