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