27#include <fmt/format.h>
36static constexpr int MAX_SIMPLE_FONT_CODES = 256;
41 unsigned aSubsetIndex,
bool aBold,
bool aItalic,
42 double aStrokeWidthFactor,
double aAspectRatio ) :
46 m_cmapName( fmt::format(
"KiCadStrokeCMap{}", aSubsetIndex ) ),
47 m_widths( MAX_SIMPLE_FONT_CODES, 0.0 ),
91 fmt::memory_buffer buffer;
97 fmt::format_to( std::back_inserter( buffer ),
"{:.3f} w 1 J 1 j ", lw );
100 for(
const std::vector<VECTOR2D>& stroke : *aGlyph )
102 bool firstPoint =
true;
104 for(
const VECTOR2D& point : stroke )
106 double x = ( point.x + cfg.m_PDFStrokeFontXOffset ) * xEm;
107 double y = point.y * yEm;
110 y += cfg.m_PDFStrokeFontYOffset * yEm;
114 fmt::format_to( std::back_inserter( buffer ),
"{:.3f} {:.3f} m ", x, y );
119 fmt::format_to( std::back_inserter( buffer ),
"{:.3f} {:.3f} l ", x, y );
123 if( !stroke.empty() )
124 fmt::format_to( std::back_inserter( buffer ),
"S " );
127 return std::string( buffer.data(), buffer.size() );
164 glyph =
m_font->GetGlyph( glyphIndex );
165 bbox =
m_font->GetGlyphBoundingBox( glyphIndex );
177 data.
m_maxX = ( origin.
x + size.
x ) * xEm;
178 data.
m_maxY = ( origin.
y + size.
y ) * yEm;
183 double newMinY = -data.
m_maxY;
184 double newMaxY = -data.
m_minY;
202 data.
m_minX -= halfStroke;
203 data.
m_minY -= halfStroke;
204 data.
m_maxX += halfStroke;
205 data.
m_maxY += halfStroke;
210 if( kerningFactor <= 0.0 )
214 data.
m_width = size.
x * xEm * kerningFactor;
215 data.
m_stream = fmt::format(
"{:.3f} 0 {:.3f} {:.3f} {:.3f} {:.3f} d1 {}",
227 m_glyphs.push_back( std::move( data ) );
253 return static_cast<int>(
m_glyphs.size() );
274 fmt::memory_buffer buffer;
275 fmt::format_to( std::back_inserter( buffer ),
"[ {} ", first );
277 for(
int code = first; code <= last; ++code )
282 fmt::format_to( std::back_inserter( buffer ),
"/{} ", glyph->
m_name );
284 fmt::format_to( std::back_inserter( buffer ),
"/.notdef " );
287 fmt::format_to( std::back_inserter( buffer ),
"]" );
288 return std::string( buffer.data(), buffer.size() );
297 fmt::memory_buffer buffer;
298 fmt::format_to( std::back_inserter( buffer ),
"[" );
300 for(
int code = first; code <= last; ++code )
301 fmt::format_to( std::back_inserter( buffer ),
" {:g}",
m_widths[code] );
303 fmt::format_to( std::back_inserter( buffer ),
" ]" );
304 return std::string( buffer.data(), buffer.size() );
310 size_t mappingCount = 0;
314 if( glyph.m_code == 0 )
320 fmt::memory_buffer buffer;
322 fmt::format_to( std::back_inserter( buffer ),
"/CIDInit /ProcSet findresource begin\n" );
323 fmt::format_to( std::back_inserter( buffer ),
"12 dict begin\n" );
324 fmt::format_to( std::back_inserter( buffer ),
"begincmap\n" );
325 fmt::format_to( std::back_inserter( buffer ),
"/CIDSystemInfo << /Registry (KiCad) /Ordering (StrokeFont) /Supplement 0 >> def\n" );
326 fmt::format_to( std::back_inserter( buffer ),
"/CMapName /{} def\n",
m_cmapName );
327 fmt::format_to( std::back_inserter( buffer ),
"/CMapType 2 def\n" );
328 fmt::format_to( std::back_inserter( buffer ),
"1 begincodespacerange\n" );
329 fmt::format_to( std::back_inserter( buffer ),
"<00> <FF>\n" );
330 fmt::format_to( std::back_inserter( buffer ),
"endcodespacerange\n" );
332 fmt::format_to( std::back_inserter( buffer ),
"{} beginbfchar\n", mappingCount );
336 if( glyph.m_code == 0 )
339 fmt::format_to( std::back_inserter( buffer ),
"<{:02X}> <{}>\n", glyph.m_code,
343 fmt::format_to( std::back_inserter( buffer ),
"endbfchar\n" );
344 fmt::format_to( std::back_inserter( buffer ),
"endcmap\n" );
345 fmt::format_to( std::back_inserter( buffer ),
"CMapName currentdict /CMap defineresource pop\n" );
346 fmt::format_to( std::back_inserter( buffer ),
"end\n" );
347 fmt::format_to( std::back_inserter( buffer ),
"end\n" );
349 return std::string( buffer.data(), buffer.size() );
355 int value =
static_cast<int>( aCode );
358 return static_cast<int>(
'?' ) -
' ';
360 int index = value -
' ';
361 int count =
static_cast<int>(
m_font ?
m_font->GetGlyphCount() : 0 );
364 return static_cast<int>(
'?' ) -
' ';
372 return fmt::format(
"g{:02X}", aCode );
380 if( glyph.m_code == aCode )
389 m_font(
KIFONT::STROKE_FONT::LoadFont( wxEmptyString ) ),
408 int aStrokeWidth,
int aFontWidth,
411 int strokeWidth =
std::abs( aStrokeWidth );
412 int fontWidth =
std::abs( aFontWidth );
413 int fontHeight = strokeWidth > 0 ?
std::abs( aFontHeight ) : 0;
414 return { aBold, aItalic, strokeWidth, fontWidth, fontHeight };
419 int aStrokeWidth,
int aFontWidth,
int aFontHeight,
bool aBold,
431 std::string currentBytes;
433 for( wxUniChar ch : aText )
446 if( subset != currentSubset )
448 if( !currentBytes.empty() && currentSubset )
449 aRuns->push_back( { currentSubset, currentBytes, aBold, aItalic } );
451 currentSubset = subset;
452 currentBytes.clear();
455 currentBytes.push_back(
static_cast<char>( code ) );
458 if( !currentBytes.empty() && currentSubset )
459 aRuns->push_back( { currentSubset, std::move( currentBytes ), aBold, aItalic } );
463 int aFontWidth,
int aFontHeight,
464 bool aBold,
bool aItalic )
466 int strokeWidth =
std::abs( aStrokeWidth );
467 int fontWidth =
std::abs( aFontWidth );
468 int fontHeight =
std::abs( aFontHeight );
472 if( strokeWidth > 0 && fontHeight > 0 )
474 widthFactor =
static_cast<double>( strokeWidth ) /
static_cast<double>( fontHeight );
480 if( widthFactor <= 0.0 )
490 widthFactor *= boldMul;
494 double aspectRatio = 1.0;
496 if( fontHeight > 0 && fontWidth > 0 )
497 aspectRatio =
static_cast<double>( fontWidth ) /
static_cast<double>( fontHeight );
499 STYLE_KEY key =
styleKey( aBold, aItalic, aStrokeWidth, aFontWidth, aFontHeight );
502 for(
const std::unique_ptr<PDF_STROKE_FONT_SUBSET>& subset :
group.subsets )
504 if( subset->Contains( aCode ) )
508 for(
const std::unique_ptr<PDF_STROKE_FONT_SUBSET>& subset :
group.subsets )
510 if( subset->IsFull() )
513 if( subset->EnsureGlyph( aCode ) >= 0 )
518 auto newSubset = std::make_unique<PDF_STROKE_FONT_SUBSET>(
m_font.get(),
m_unitsPerEm, subsetIndex, aBold, aItalic,
519 widthFactor, aspectRatio );
522 group.subsets.emplace_back( std::move( newSubset ) );
528 std::vector<PDF_STROKE_FONT_SUBSET*> out;
533 for(
const auto&
up :
group.subsets )
534 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
unsigned m_nextSubsetIndex
std::map< STYLE_KEY, STYLE_GROUP > m_styleGroups
void EncodeString(const wxString &aText, std::vector< PDF_STROKE_FONT_RUN > *aRuns, int aStrokeWidth, int aFontWidth, int aFontHeight, bool aBold=false, bool aItalic=false)
std::tuple< bool, bool, int, int, int > STYLE_KEY
PDF_STROKE_FONT_SUBSET * ensureSubsetForGlyph(wxUniChar aCode, int aStrokeWidth, int aFontWidth, int aFontHeight, bool aBold, bool aItalic)
std::vector< PDF_STROKE_FONT_SUBSET * > AllSubsets() const
static STYLE_KEY styleKey(bool aBold, bool aItalic, int aStrokeWidth, int aFontWidth, int aFontHeight)
PDF_STROKE_FONT_MANAGER()
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
double m_strokeWidthFactor
std::string BuildToUnicodeCMap() const
bool Contains(wxUniChar aCode) const
PDF_STROKE_FONT_SUBSET(const KIFONT::STROKE_FONT *aFont, double aUnitsPerEm, unsigned aSubsetIndex, bool aBold, bool aItalic, double aStrokeWidthFactor, double aAspectRatio)
std::vector< GLYPH > m_glyphs
const GLYPH * glyphForCode(int aCode) const
std::string buildGlyphStream(const KIFONT::STROKE_GLYPH *aGlyph) const
int glyphIndexForUnicode(wxUniChar aCode) const
double m_PDFStrokeFontKerningFactor
Kerning (spacing) factor applied to glyph advance (width).
double m_PDFStrokeFontXOffset
Horizontal offset factor applied to stroke font glyph coordinates (in EM units) after to compensate m...
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.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
std::string FormatPdfUtf16Hex(uint32_t aCodepoint)
Format one Unicode code point as the hex digits of its UTF-16BE representation.
VECTOR2< double > VECTOR2D