31#include <wx/filename.h> 
   32#include <wx/mstream.h> 
   33#include <wx/zstream.h> 
   34#include <wx/wfstream.h> 
   35#include <wx/datstrm.h> 
   36#include <wx/tokenzr.h> 
   49#include <fmt/format.h> 
   50#include <fmt/chrono.h> 
   51#include <fmt/ranges.h> 
   62#define GLM_ENABLE_EXPERIMENTAL  
   64#include <glm/gtx/euler_angles.hpp> 
   75    bool is_ascii7 = 
true;
 
   77    for( 
size_t ii = 0; ii < aText.Len(); ii++ )
 
   79        if( aText[ii] >= 0x7F )
 
   90        for( 
unsigned ii = 0; ii < aText.Len(); ii++ )
 
   92            unsigned int code = aText[ii];
 
  115        for( 
size_t ii = 0; ii < aText.Len(); ii++ )
 
  117            unsigned int code = aText[ii];
 
  118            result += fmt::format(
"{:04X}", code);
 
 
  131    result.reserve( aBytes.size() * 4 + 2 );
 
  134    for( 
unsigned char byte : aBytes )
 
  136        if( 
byte == 
'(' || 
byte == 
')' || 
byte == 
'\\' )
 
  139            result.push_back( 
static_cast<char>( 
byte ) );
 
  141        else if( byte < 32 || byte > 126 )
 
  143            fmt::format_to( std::back_inserter( 
result ), 
"\\{:03o}", 
byte );
 
  147            result.push_back( 
static_cast<char>( 
byte ) );
 
 
  173                               double aScale, 
bool aMirror )
 
 
  200    wxASSERT_MSG( aWidth > 0, 
"Plotter called to set negative pen width" );
 
 
  217        r = ( r * a ) + ( 1 - a );
 
  218        g = ( g * a ) + ( 1 - a );
 
  219        b = ( b * a ) + ( 1 - a );
 
  222    fmt::println( 
m_workFile, 
"{:g} {:g} {:g} rg {:g} {:g} {:g} RG", r, g, b, r, g, b );
 
 
  245        fmt::println( 
m_workFile, 
"[{} {} {} {}] 0 d",
 
  253        fmt::println( 
m_workFile, 
"[{} {} {} {} {} {}] 0 d",
 
 
  278    if( aCornerRadius > 0 )
 
  290    if( size.
x == 0 && size.
y == 0 )
 
  302        std::vector<VECTOR2I> cornerList;
 
  304        cornerList.emplace_back( p1.
x, p1.
y );
 
  305        cornerList.emplace_back( p2.
x, p1.
y );
 
  306        cornerList.emplace_back( p2.
x, p2.
y );
 
  307        cornerList.emplace_back( p1.
x, p2.
y );
 
  308        cornerList.emplace_back( p1.
x, p1.
y );
 
  310        PlotPoly( cornerList, fill, width, 
nullptr );
 
  323        paintOp = width > 0 ? 
'B' : 
'f';
 
  325    fmt::println( 
m_workFile, 
"{:g} {:g} {:g} {:g} re {}",
 
 
  359    double magic = 
radius * 0.551784; 
 
  364                  "{:g} {:g} {:g} {:g} {:g} {:g} c " 
  365                  "{:g} {:g} {:g} {:g} {:g} {:g} c " 
  366                  "{:g} {:g} {:g} {:g} {:g} {:g} c " 
  367                  "{:g} {:g} {:g} {:g} {:g} {:g} c {}",
 
  370                  pos_dev.
x - 
radius, pos_dev.
y + magic,
 
  371                  pos_dev.
x - magic, pos_dev.
y + 
radius,
 
  374                  pos_dev.
x + magic, pos_dev.
y + 
radius,
 
  375                  pos_dev.
x + 
radius, pos_dev.
y + magic,
 
  378                  pos_dev.
x + 
radius, pos_dev.
y - magic,
 
  379                  pos_dev.
x + magic, pos_dev.
y - 
radius,
 
  382                  pos_dev.
x - magic, pos_dev.
y - 
radius,
 
  383                  pos_dev.
x - 
radius, pos_dev.
y - magic,
 
 
  391                                            const EDA_ANGLE& aAngle, 
double aRadius )
 
  393    std::vector<VECTOR2D> 
path;
 
  400    EDA_ANGLE       endAngle = startAngle - aAngle;
 
  405    if( startAngle > endAngle )
 
  406        std::swap( startAngle, endAngle );
 
  409    start.
x = 
KiROUND( aCenter.
x + aRadius * ( -startAngle ).Cos() );
 
  410    start.
y = 
KiROUND( aCenter.
y + aRadius * ( -startAngle ).Sin() );
 
  415        end.x = 
KiROUND( aCenter.
x + aRadius * ( -ii ).Cos() );
 
  416        end.y = 
KiROUND( aCenter.
y + aRadius * ( -ii ).Sin() );
 
  420    end.x = 
KiROUND( aCenter.
x + aRadius * ( -endAngle ).Cos() );
 
  421    end.y = 
KiROUND( aCenter.
y + aRadius * ( -endAngle ).Sin() );
 
 
  441    std::vector<VECTOR2D> 
path = 
arcPath( aCenter, aStartAngle, aAngle, aRadius );
 
  443    if( 
path.size() >= 2 )
 
  447        for( 
int ii = 1; ii < (int) 
path.size(); ++ii )
 
  460        fmt::println( 
m_workFile, 
"{:g} {:g} l b", pos_dev.
x, pos_dev.
y );
 
 
  470    if( aCornerList.size() <= 1 )
 
  481    for( 
unsigned ii = 1; ii < aCornerList.size(); ii++ )
 
  490    else if( aWidth == 0 )
 
 
  501    std::set<size_t>      handledArcs;
 
  502    std::vector<VECTOR2D> 
path;
 
  508            size_t arcIndex = aLineChain.
ArcIndex( ii );
 
  510            if( !handledArcs.contains( arcIndex ) )
 
  512                handledArcs.insert( arcIndex );
 
  517                for( 
const VECTOR2D& pt : std::ranges::reverse_view( arc_path ) )
 
  518                    path.emplace_back( pt );
 
  529    if( 
path.size() <= 1 )
 
  534    for( 
int ii = 1; ii < (int) 
path.size(); ++ii )
 
  540    else if( aWidth == 0 )
 
 
  570                      plume == 
'D' ? 
'l' : 
'm' );
 
 
  581    VECTOR2I pix_size( aImage.GetWidth(), aImage.GetHeight() );
 
  584    VECTOR2D drawsize( aScaleFactor * pix_size.
x, aScaleFactor * pix_size.
y );
 
  587    VECTOR2I start( aPos.
x - drawsize.
x / 2, aPos.
y + drawsize.
y / 2 );
 
  591    auto findHandleForImage =
 
  592            [&]( 
const wxImage& aCurrImage ) -> 
int 
  596                    if( 
image.IsSameAs( aCurrImage ) )
 
  599                    if( 
image.GetWidth() != aCurrImage.GetWidth() )
 
  602                    if( 
image.GetHeight() != aCurrImage.GetHeight() )
 
  605                    if( 
image.GetType() != aCurrImage.GetType() )
 
  608                    if( 
image.HasAlpha() != aCurrImage.HasAlpha() )
 
  611                    if( 
image.HasMask() != aCurrImage.HasMask()
 
  612                      || 
image.GetMaskRed() != aCurrImage.GetMaskRed()
 
  613                      || 
image.GetMaskGreen() != aCurrImage.GetMaskGreen()
 
  614                      || 
image.GetMaskBlue() != aCurrImage.GetMaskBlue() )
 
  617                    int pixCount = 
image.GetWidth() * 
image.GetHeight();
 
  619                    if( memcmp( 
image.GetData(), aCurrImage.GetData(), pixCount * 3 ) != 0 )
 
  622                    if( 
image.HasAlpha() && memcmp( 
image.GetAlpha(), aCurrImage.GetAlpha(), pixCount ) != 0 )
 
  631    int imgHandle = findHandleForImage( aImage );
 
  633    if( imgHandle == -1 )
 
  649    fmt::println( 
m_workFile, 
"q {:g} 0 0 {:g} {:g} {:g} cm", 
 
  655    fmt::println( 
m_workFile, 
"/Im{} Do", imgHandle );
 
 
  702                     "<< /Length {} 0 R >>\nstream\n",
 
  708                     "<< /Length {} 0 R /Filter /FlateDecode >>\nstream\n",
 
 
  734    unsigned char *inbuf = 
new unsigned char[stream_len];
 
  736    int rc = fread( inbuf, 1, stream_len, 
m_workFile );
 
  737    wxASSERT( rc == stream_len );
 
  749        out_count = stream_len;
 
  755        wxMemoryOutputStream    memos( 
nullptr, std::max( 2000l, stream_len ) ) ;
 
  765            wxZlibOutputStream      zos( memos, wxZ_BEST_COMPRESSION, wxZLIB_ZLIB );
 
  767            zos.Write( inbuf, stream_len );
 
  770        wxStreamBuffer* sb = memos.GetOutputStreamBuffer();
 
  772        out_count = sb->Tell();
 
  773        fwrite( sb->GetBufferStart(), 1, out_count, 
m_outputFile );
 
 
  788                             const wxString& aParentPageNumber, 
const wxString& aParentPageName )
 
  794    m_pageName = aPageName.IsEmpty() ? wxString::Format( 
_( 
"Page %s" ),
 
  796                                     : wxString::Format( 
_( 
"%s (Page %s)" ),
 
  801                                                 : wxString::Format( 
_( 
"%s (Page %s)" ),
 
  824                      "{:g} 0 0 {:g} 0 0 cm 1 J 1 j 0 0 0 rg 0 0 0 RG {:g} w",
 
 
  831void WriteImageStream( 
const wxImage& aImage, wxDataOutputStream& aOut, wxColor bg, 
bool colorMode )
 
  833    int w = aImage.GetWidth();
 
  834    int h = aImage.GetHeight();
 
  836    for( 
int y = 0; y < h; y++ )
 
  838        for( 
int x = 0; x < w; x++ )
 
  840            unsigned char r = aImage.GetRed( x, y ) & 0xFF;
 
  841            unsigned char g = aImage.GetGreen( x, y ) & 0xFF;
 
  842            unsigned char b = aImage.GetBlue( x, y ) & 0xFF;
 
  844            if( aImage.HasMask() )
 
  846                if( r == aImage.GetMaskRed() && g == aImage.GetMaskGreen()
 
  847                    && b == aImage.GetMaskBlue() )
 
  864                unsigned char grey = 
KiROUND( r * 0.2126 + g * 0.7152 + b * 0.0722 );
 
 
  875    int w = aImage.GetWidth();
 
  876    int h = aImage.GetHeight();
 
  878    if( aImage.HasMask() )
 
  880        for( 
int y = 0; y < h; y++ )
 
  882            for( 
int x = 0; x < w; x++ )
 
  884                unsigned char a = 255;
 
  885                unsigned char r = aImage.GetRed( x, y );
 
  886                unsigned char g = aImage.GetGreen( x, y );
 
  887                unsigned char b = aImage.GetBlue( x, y );
 
  889                if( r == aImage.GetMaskRed() && g == aImage.GetMaskGreen()
 
  890                    && b == aImage.GetMaskBlue() )
 
  899    else if( aImage.HasAlpha() )
 
  902        aOut.Write8( aImage.GetAlpha(), size );
 
 
  921    const double PTsPERMIL = 0.072;
 
  924    auto iuToPdfUserSpace =
 
  937                        retval.
x = ( psPaperSize.
x - pos.
x );
 
  946    std::vector<int> annotHandles;
 
  952        const BOX2I&    box = linkPair.first;
 
  953        const wxString& url = linkPair.second;
 
  960        userSpaceBox.
SetEnd( topRight );
 
  969        const BOX2I&                 box = menuPair.first;
 
  970        const std::vector<wxString>& urls = menuPair.second;
 
  977        userSpaceBox.
SetEnd( topRight );
 
  984    int annot3DHandle = -1;
 
  989        annotHandles.push_back( annot3DHandle );
 
  993    int annotArrayHandle = -1;
 
  996    if( annotHandles.size() > 0 )
 
 1003        for( 
int handle : annotHandles )
 
 1026                "    /ProcSet [/PDF /Text /ImageC /ImageB]\n" 
 1028                "    /XObject {} 0 R >>\n" 
 1029                "/MediaBox [0 0 {:g} {:g}]\n",
 
 1039    if( annotHandles.size() > 0 )
 
 1040        fmt::print( 
m_outputFile, 
"/Annots {} 0 R", annotArrayHandle );
 
 1053                    "/Rect [0 0 {:g} {:g}]\n" 
 1054                    "/NM (3D Annotation)\n" 
 1057                    "/3DA<</A/PO/D/PC/TB true/NP true>>\n" 
 1075        std::stack<OUTLINE_NODE*> nodes;
 
 1078        while( !nodes.empty() )
 
 1092                nodes.push( child );
 
 1104        for( 
const std::pair<BOX2I, wxString>& bookmarkPair : groupVector )
 
 1106            const BOX2I&    box = bookmarkPair.first;
 
 1107            const wxString& ref = bookmarkPair.second;
 
 1112            actionHandle = 
emitGoToAction( pageHandle, bottomLeft, topRight );
 
 1117        std::sort( groupOutlineNode->
children.begin(), groupOutlineNode->
children.end(),
 
 1120                       return a->title < b->title;
 
 
 1133    return StartPlot( aPageNumber, wxEmptyString );
 
 
 1166    fmt::print( 
m_outputFile, 
"%PDF-1.5\n%\200\201\202\203\n" );
 
 
 1194                "<</S /GoTo /D [{} 0 R /FitR {} {} {} {}]\n" 
 1204    return actionHandle;
 
 
 1214                  "<</S /GoTo /D [{} 0 R /Fit]\n" 
 1220    return actionHandle;
 
 
 1228    int prevHandle = -1;
 
 1229    int nextHandle = -1;
 
 1231    for( std::vector<OUTLINE_NODE*>::iterator it = node->
children.begin();
 
 1234        if( it >= node->
children.end() - 1 )
 
 1240            nextHandle = ( *( it + 1 ) )->entryHandle;
 
 1245        prevHandle = ( *it )->entryHandle;
 
 1249    if( parentHandle != -1 )
 
 1262            fmt::println( 
m_outputFile, 
"/Next {} 0 R", nextNode );
 
 1267            fmt::println( 
m_outputFile, 
"/Prev {} 0 R", prevNode );
 
 1272            int32_t count = -1 * 
static_cast<int32_t
>( node->
children.size() );
 
 
 1290                                                        const wxString& aTitle )
 
 
 1311                    "<< /Type /Outlines\n" 
 
 1350            if( !glyph.m_stream.empty() )
 
 1351                fmt::print( 
m_workFile, 
"{}\n", glyph.m_stream );
 
 1354            glyph.m_charProcHandle = charProcHandle;
 
 1361            fmt::println( 
m_outputFile, 
"    /{} {} 0 R", glyph.m_name, glyph.m_charProcHandle );
 
 1376        double fontMatrixScale = 1.0 / subset.
UnitsPerEm();
 
 1384                    "<<\n/Type /Font\n/Subtype /Type3\n/Name {}\n/FontBBox [ {:g} {:g} {:g} {:g} ]\n",
 
 1391                    "/FontMatrix [ {:g} 0 0 {:g} 0 0 ]\n/CharProcs {} 0 R\n",
 
 1396                    "/Encoding << /Type /Encoding /Differences {} >>\n",
 
 1399                    "/FirstChar {}\n/LastChar {}\n/Widths {}\n",
 
 1404                    "/ToUnicode {} 0 R\n/Resources << /ProcSet [/PDF /Text] >>\n>>\n",
 
 
 1419        if( !subsetPtr || !subsetPtr->HasGlyphs() )
 
 1422        const std::vector<uint8_t>& fontData = subsetPtr->FontFileData();
 
 1424        if( fontData.empty() )
 
 1428        subsetPtr->SetFontFileHandle( fontFileHandle );
 
 1430        if( !fontData.empty() )
 
 1431            fwrite( fontData.data(), fontData.size(), 1, 
m_workFile );
 
 1435        std::string cidMap = subsetPtr->BuildCIDToGIDStream();
 
 1437        subsetPtr->SetCIDMapHandle( cidMapHandle );
 
 1439        if( !cidMap.empty() )
 
 1440            fwrite( cidMap.data(), cidMap.size(), 1, 
m_workFile );
 
 1444        std::string toUnicode = subsetPtr->BuildToUnicodeCMap();
 
 1446        subsetPtr->SetToUnicodeHandle( toUnicodeHandle );
 
 1448        if( !toUnicode.empty() )
 
 1454        subsetPtr->SetFontDescriptorHandle( descriptorHandle );
 
 1457                    "<<\n/Type /FontDescriptor\n/FontName /{}\n/Flags {}\n/ItalicAngle {:g}\n/Ascent {:g}\n/Descent {:g}\n" 
 1458                    "/CapHeight {:g}\n/StemV {:g}\n/FontBBox [ {:g} {:g} {:g} {:g} ]\n/FontFile2 {} 0 R\n>>\n",
 
 1459                    subsetPtr->BaseFontName(),
 
 1461                    subsetPtr->ItalicAngle(),
 
 1462                    subsetPtr->Ascent(),
 
 1463                    subsetPtr->Descent(),
 
 1464                    subsetPtr->CapHeight(),
 
 1466                    subsetPtr->BBoxMinX(),
 
 1467                    subsetPtr->BBoxMinY(),
 
 1468                    subsetPtr->BBoxMaxX(),
 
 1469                    subsetPtr->BBoxMaxY(),
 
 1470                    subsetPtr->FontFileHandle() );
 
 1474        subsetPtr->SetCIDFontHandle( cidFontHandle );
 
 1476        std::string widths = subsetPtr->BuildWidthsArray();
 
 1479                    "<<\n/Type /Font\n/Subtype /CIDFontType2\n/BaseFont /{}\n" 
 1480                    "/CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >>\n" 
 1481                    "/FontDescriptor {} 0 R\n/W {}\n/CIDToGIDMap {} 0 R\n>>\n",
 
 1482                    subsetPtr->BaseFontName(),
 
 1483                    subsetPtr->FontDescriptorHandle(),
 
 1485                    subsetPtr->CIDMapHandle() );
 
 1489        subsetPtr->SetFontHandle( fontHandle );
 
 1492                    "<<\n/Type /Font\n/Subtype /Type0\n/BaseFont /{}\n/Encoding /Identity-H\n" 
 1493                    "/DescendantFonts [ {} 0 R ]\n/ToUnicode {} 0 R\n>>\n",
 
 1494                    subsetPtr->BaseFontName(),
 
 1495                    subsetPtr->CIDFontHandle(),
 
 1496                    subsetPtr->ToUnicodeHandle() );
 
 
 1514            if( subsetPtr && subsetPtr->FontHandle() >= 0 )
 
 1515                fmt::println( 
m_outputFile, 
"    {} {} 0 R", subsetPtr->ResourceName(), subsetPtr->FontHandle() );
 
 1538        fmt::print( 
m_outputFile, 
"    /Im{} {} 0 R\n", imgHandle, imgHandle );
 
 1559                    "/BitsPerComponent 8\n" 
 1563                    "/Filter /FlateDecode\n" 
 1570        if( smaskHandle != -1 )
 
 1571            fmt::println( 
m_outputFile, 
"/SMask {} 0 R", smaskHandle );
 
 1579            wxFFileOutputStream ffos( outputFFile );
 
 1580            wxZlibOutputStream  zos( ffos, wxZ_BEST_COMPRESSION, wxZLIB_ZLIB );
 
 1581            wxDataOutputStream  dos( zos );
 
 1587        long imgStreamSize = ftell( 
m_outputFile ) - imgStreamStart;
 
 1596        if( smaskHandle != -1 )
 
 1606                        "/BitsPerComponent 8\n" 
 1607                        "/ColorSpace /DeviceGray\n" 
 1611                        "/Filter /FlateDecode\n" 
 1622                wxFFileOutputStream ffos( outputFFile );
 
 1623                wxZlibOutputStream  zos( ffos, wxZ_BEST_COMPRESSION, wxZLIB_ZLIB );
 
 1624                wxDataOutputStream  dos( zos );
 
 1629            long smaskStreamSize = ftell( 
m_outputFile ) - smaskStreamStart;
 
 1635            fmt::println( 
m_outputFile, 
"{}", (
unsigned) smaskStreamSize );
 
 1639        outputFFile.Detach(); 
 
 1644        BOX2D    box = linkPair.first;
 
 1645        wxString url = linkPair.second;
 
 1653                    "/Rect [{:g} {:g} {:g} {:g}]\n" 
 1654                    "/Border [16 16 0]\n",
 
 1660        wxString pageNumber;
 
 1661        bool     pageFound = 
false;
 
 1670                                "/Dest [{} 0 R /FitB]\n" 
 1682                fmt::print( 
m_outputFile, 
"/A << /Type /Action /S /NOP >>\n" 
 1692                        "/A << /Type /Action /S /URI /URI {} >>\n" 
 1702        const BOX2D&                 box = menuPair.first;
 
 1703        const std::vector<wxString>& urls = menuPair.second;
 
 1704        wxString                     js = wxT( 
"ShM([\n" );
 
 1706        for( 
const wxString& url : urls )
 
 1708            if( url.StartsWith( 
"!" ) )
 
 1710                wxString 
property = url.AfterFirst( 
'!' );
 
 1712                if( property.Find( 
"http:" ) >= 0 )
 
 1714                    wxString href = 
property.substr( property.Find( 
"http:" ) );
 
 1719                    js += wxString::Format( wxT( 
"[\"%s\", \"%s\"],\n" ),
 
 1723                else if( property.Find( 
"https:" ) >= 0 )
 
 1725                    wxString href = 
property.substr( property.Find( 
"https:" ) );
 
 1730                    js += wxString::Format( wxT( 
"[\"%s\", \"%s\"],\n" ),
 
 1734                else if( property.Find( 
"file:" ) >= 0 )
 
 1736                    wxString href = 
property.substr( property.Find( 
"file:" ) );
 
 1743                    js += wxString::Format( wxT( 
"[\"%s\", \"%s\"],\n" ),
 
 1749                    js += wxString::Format( wxT( 
"[\"%s\"],\n" ),
 
 1753            else if( url.StartsWith( 
"#" ) )
 
 1755                wxString pageNumber = url.AfterFirst( 
'#' );
 
 1761                        wxString menuText = wxString::Format( 
_( 
"Show Page %s" ), pageNumber );
 
 1763                        js += wxString::Format( wxT( 
"[\"%s\", \"#%d\"],\n" ),
 
 1765                                                static_cast<int>( ii ) );
 
 1770            else if( url.StartsWith( 
"http:" ) || url.StartsWith( 
"https:" )
 
 1771                   || url.StartsWith( 
"file:" ) )
 
 1773                wxString href = url;
 
 1778                if( url.StartsWith( 
"file:" ) )
 
 1781                wxString menuText = wxString::Format( 
_( 
"Open %s" ), href );
 
 1783                js += wxString::Format( wxT( 
"[\"%s\", \"%s\"],\n" ),
 
 1797                    "/Rect [{:g} {:g} {:g} {:g}]\n" 
 1798                    "/Border [16 16 0]\n",
 
 1802                 "/A << /Type /Action /S /JavaScript /JS {} >>\n" 
 1813function ShM(aEntries) { 
 1815    for (var i in aEntries) { 
 1817            cName: aEntries[i][0], 
 1818            cReturn: aEntries[i][1] 
 1822    var cChoice = app.popUpMenuEx.apply(app, aParams); 
 1823    if (cChoice != null && cChoice.substring(0, 1) == '#') this.pageNum = parseInt(cChoice.slice(1)); 
 1824    else if (cChoice != null && cChoice.substring(0, 4) == 'http') app.launchURL(cChoice); 
 1825    else if (cChoice != null && cChoice.substring(0, 4) == 'file') app.openDoc(cChoice.substring(7)); 
 1832                    "    [ (JSInit) << /Type /Action /S /JavaScript /JS {} >> ]\n" 
 
 1875    std::string dt = fmt::format( 
"D:{:%Y:%m:%d:%H:%M:%S}", fmt::localtime( std::time( 
nullptr ) ) );
 
 1886                "/Producer (KiCad PDF)\n" 
 1887                "/CreationDate ({})\n" 
 1902    int outlineHandle = -1;
 
 1911    if( outlineHandle > 0 )
 
 1918                      "/PageMode /UseOutlines\n" 
 1919                      "/Outlines {} 0 R\n" 
 1921                      "/PageLayout /SinglePage\n" 
 1934                      "/PageMode /UseNone\n" 
 1935                      "/PageLayout /SinglePage\n" 
 1949                "0000000000 65535 f \n",
 
 1952    for( 
unsigned i = 1; i < 
m_xrefTable.size(); i++ )
 
 1960                "<< /Size {} /Root {} 0 R /Info {} 0 R >>\n" 
 
 1978                        const wxString&        aText,
 
 1986                        bool                   aMultilineAllowed,
 
 1992    if( aSize.
x == 0 || aSize.
y == 0 )
 
 1995    wxString 
text( aText );
 
 1997    if( 
text.Contains( wxS( 
"@{" ) ) )
 
 2010    bool     textMirrored = aSize.
x < 0;
 
 2018    std::unique_ptr<MARKUP::NODE> markupTree( markupParser.
Parse() );
 
 2022        wxLogTrace( 
tracePdfPlotter, 
"PDF_PLOTTER::Text: Markup parsing failed, falling back to plain text." );
 
 2024        wxStringTokenizer str_tok( 
text, 
" ", wxTOKEN_RET_DELIMS );
 
 2027        while( str_tok.HasMoreTokens() )
 
 2029            wxString word = str_tok.GetNextToken();
 
 2030            pos = 
renderWord( word, pos, t_size, aOrient, textMirrored, aWidth, aBold, aItalic, aFont,
 
 2031                              aFontMetrics, aV_justify, 0 );
 
 2060    std::vector<OVERBAR_INFO> overbars;
 
 2061    renderMarkupNode( markupTree.get(), pos, t_size, aOrient, textMirrored, aWidth,
 
 2062                      aBold, aItalic, aFont, aFontMetrics, aV_justify, 0, overbars );
 
 
 2071                                  bool aTextMirrored, 
int aWidth, 
bool aBold, 
bool aItalic,
 
 2075    if( wxGetEnv( 
"KICAD_DEBUG_SYN_STYLE", 
nullptr ) )
 
 2080        wxLogTrace( 
tracePdfPlotter, 
"renderWord enter word='%s' bold=%d italic=%d textStyle=%u styleFlags=%d", 
TO_UTF8( aWord ), (
int) aBold, (
int) aItalic, (
unsigned) aTextStyle, styleFlags );
 
 2088    if( aWord == wxT(
" ") )
 
 2096        VECTOR2I rotatedSpaceBox = spaceBox;
 
 2098        return aPosition + rotatedSpaceBox;
 
 2102    double ctm_a, ctm_b, ctm_c, ctm_d, ctm_e, ctm_f;
 
 2103    double wideningFactor, heightFactor;
 
 2107                           &ctm_a, &ctm_b, &ctm_c, &ctm_d, &ctm_e, &ctm_f, &heightFactor );
 
 2116    VECTOR2I nextPos = aPosition + bbox;
 
 2123        double factor = aFont->
IsOutline() ? 0.050 : 0.030; 
 
 2124        VECTOR2I offset( 0, 
static_cast<int>( std::lround( aSize.
y * factor ) ) );
 
 2135            offset.
y = 
static_cast<int>( std::lround( aSize.
y * 0.01 ) );
 
 2145        std::vector<PDF_OUTLINE_FONT_RUN> outlineRuns;
 
 2155        if( !outlineRuns.empty() )
 
 2158            double baseline_factor = 0.17;
 
 2159            double alignment_multiplier = 1.0;
 
 2162                alignment_multiplier = 2.0;
 
 2164                alignment_multiplier = 4.0;
 
 2167            double baseline_adjustment = font_size_dev.
y * baseline_factor * alignment_multiplier;
 
 2169            double adjusted_ctm_e = ctm_e;
 
 2170            double adjusted_ctm_f = ctm_f;
 
 2173            double cos_angle = cos( angle_rad );
 
 2174            double sin_angle = sin( angle_rad );
 
 2176            adjusted_ctm_e = ctm_e - baseline_adjustment * sin_angle;
 
 2177            adjusted_ctm_f = ctm_f + baseline_adjustment * cos_angle;
 
 2179            double adj_c = ctm_c;
 
 2180            double adj_d = ctm_d;
 
 2183            bool syntheticItalicApplied = 
false;
 
 2184            double appliedTilt = 0.0;
 
 2185            double syn_c = adj_c;
 
 2186            double syn_d = adj_d;
 
 2187            double syn_a = ctm_a;
 
 2188            double syn_b = ctm_b;
 
 2191            if( std::getenv( 
"KICAD_FORCE_SYN_ITALIC" ) )
 
 2195            bool fontIsItalic = aFont->
IsItalic();
 
 2196            bool fontIsBold   = aFont->
IsBold();
 
 2204            bool forceSynItalic = 
false;
 
 2205            double overrideTilt = 0.0;
 
 2207            if( 
const char* envForce = std::getenv( 
"KICAD_FORCE_SYN_ITALIC" ) )
 
 2209                if( *envForce != 
'\0' && *envForce != 
'0' )
 
 2210                    forceSynItalic = 
true;
 
 2213            if( 
const char* envTilt = std::getenv( 
"KICAD_SYN_ITALIC_TILT" ) )
 
 2215                std::string tiltStr( envTilt );
 
 2219                    if( tiltStr.find( 
"deg" ) != std::string::npos )
 
 2221                        double deg = std::stod( tiltStr );
 
 2222                        overrideTilt = tan( deg * 
M_PI / 180.0 );
 
 2226                        overrideTilt = std::stod( tiltStr );
 
 2237                        "Outline path word='%s' runs=%zu wantItalic=%d fontIsItalic=%d fontIsFakeItalic=%d wantBold=%d fontIsBold=%d fontIsFakeBold=%d forceSyn=%d",
 
 2238                        TO_UTF8( aWord ), outlineRuns.size(), (
int) wantItalic, (
int) fontIsItalic,
 
 2239                        (
int) fontIsFakeItalic, (
int) wantBold, (
int) fontIsBold, (
int) fontIsFakeBold,
 
 2240                        (
int) forceSynItalic );
 
 2246            bool realItalicFace = fontIsItalic && !fontIsFakeItalic;
 
 2248            if( wantItalic && ( forceSynItalic || !realItalicFace ) )
 
 2259                double tilt = ( overrideTilt != 0.0 ) ? overrideTilt : 
ITALIC_TILT;
 
 2261                if( wideningFactor < 0 )       
 
 2264                syn_c = adj_c + tilt * syn_a;
 
 2265                syn_d = adj_d + tilt * syn_b;
 
 2267                syntheticItalicApplied = 
true;
 
 2269                wxLogTrace( 
tracePdfPlotter, 
"Synthetic italic shear applied: tilt=%f a=%f b=%f c->%f d->%f",
 
 2270                            tilt, syn_a, syn_b, syn_c, syn_d );
 
 2273            if( wantBold && !fontIsBold )
 
 2280            if( syntheticItalicApplied )
 
 2283                fmt::print( 
m_workFile, 
"% syn-italic tilt={} a={} b={} c={} d={}\n",
 
 2284                            appliedTilt, syn_a, syn_b, syn_c, syn_d );
 
 2287            fmt::print( 
m_workFile, 
"q {:f} {:f} {:f} {:f} {:f} {:f} cm BT {} Tr {:g} Tz ",
 
 2288                        syn_a, syn_b, syn_c, syn_d, adjusted_ctm_e, adjusted_ctm_f,
 
 2290                        wideningFactor * 100 );
 
 2294                fmt::print( 
m_workFile, 
"{} {:g} Tf <", run.m_subset->ResourceName(), heightFactor );
 
 2299                                static_cast<unsigned char>( ( glyph.
cid >> 8 ) & 0xFF ),
 
 2300                                static_cast<unsigned char>( glyph.
cid & 0xFF ) );
 
 2316        wxLogTrace( 
tracePdfPlotter, 
"Stroke path word='%s' wantItalic=%d aItalic=%d aBold=%d",
 
 2319        std::vector<PDF_STROKE_FONT_RUN> runs;
 
 2325            double fontSize = dev_size.
y;
 
 2327            double adj_c = ctm_c;
 
 2328            double adj_d = ctm_d;
 
 2334                if( wideningFactor < 0 )
 
 2337                adj_c -= ctm_a * tilt;
 
 2338                adj_d -= ctm_b * tilt;
 
 2341            fmt::print( 
m_workFile, 
"q {:f} {:f} {:f} {:f} {:f} {:f} cm BT {} Tr {:g} Tz ",
 
 2342                        ctm_a, ctm_b, adj_c, adj_d, ctm_e, ctm_f,
 
 2344                        wideningFactor * 100 );
 
 2349                            run.m_subset->ResourceName(),
 
 
 2365                                         bool aTextMirrored, 
int aWidth, 
bool aBaseBold, 
bool aBaseItalic,
 
 2368                                         std::vector<OVERBAR_INFO>& aOverbars )
 
 2373        return nextPosition;
 
 2377    bool drawOverbar = 
false;
 
 2380    if( !aNode->is_root() )
 
 2386            currentSize = 
VECTOR2I( aBaseSize.
x * 0.5, aBaseSize.
y * 0.6 );
 
 2392            currentSize = 
VECTOR2I( aBaseSize.
x * 0.5, aBaseSize.
y * 0.6 );
 
 2402        if( aNode->has_content() )
 
 2407            wxStringTokenizer str_tok( nodeText, 
" ", wxTOKEN_RET_DELIMS );
 
 2409            while( str_tok.HasMoreTokens() )
 
 2411                wxString word = str_tok.GetNextToken();
 
 2412                nextPosition = 
renderWord( word, nextPosition, currentSize, aOrient, aTextMirrored,
 
 2415                                           aFont, aFontMetrics, aV_justify, currentStyle );
 
 2421    for( 
const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
 
 2425        nextPosition = 
renderMarkupNode( child.get(), nextPosition, currentSize, aOrient,
 
 2426                                         aTextMirrored, aWidth, aBaseBold, aBaseItalic,
 
 2427                                         aFont, aFontMetrics, aV_justify, currentStyle, aOverbars );
 
 2433            aOverbars.push_back( { startPos, endPos, currentSize, aFont->
IsOutline(), aV_justify } );
 
 2437    return nextPosition;
 
 
 2447        VECTOR2D dir( overbar.endPos.x - overbar.startPos.x, overbar.endPos.y - overbar.startPos.y );
 
 2449        double len = hypot( dir.
x, dir.
y );
 
 2470        if( overbar.isOutline )
 
 2471            barOffset += overbar.fontSize.y * 0.16;
 
 2473            barOffset += overbar.fontSize.y * 0.32;
 
 2478        double alignMult = 1.0;
 
 2480        switch( overbar.vAlign )
 
 2484        default:                     alignMult = 1.0; 
break; 
 
 2487        if( alignMult > 1.0 )
 
 2490            double baseline_factor = 0.17;
 
 2491            barOffset += ( alignMult - 1.0 ) * ( baseline_factor * overbar.fontSize.y );
 
 2495        double barTrim = overbar.fontSize.x * 0.1;
 
 2498        VECTOR2D startPt( overbar.startPos.x, overbar.startPos.y );
 
 2499        VECTOR2D endPt( overbar.endPos.x, overbar.endPos.y );
 
 2503        VECTOR2D offVec( -barOffset * nrm.
x, -barOffset * nrm.
y );
 
 2505        startPt.
x += dir.
x * barTrim + offVec.
x;
 
 2506        startPt.
y += dir.
y * barTrim + offVec.
y;
 
 2507        endPt.
x -= dir.
x * barTrim - offVec.
x; 
 
 2508        endPt.
y -= dir.
y * barTrim - offVec.
y;
 
 
 2522                            const wxString&        aText,
 
 2531    if( size.
x == 0 || size.
y == 0 )
 
 
 2556                            const wxString &aGroupName )
 
 2559    m_bookmarksInPage[aGroupName].push_back( std::make_pair( aLocation, aSymbolReference ) );
 
 
 2564                               const std::vector<PDF_3D_VIEW>& a3DViews )
 
 2566    std::map<float, int> m_fovMap;
 
 2567    std::vector<int>     m_viewHandles;
 
 2572        wxASSERT( view.m_cameraMatrix.size() == 12 );
 
 2575        if( !m_fovMap.contains( view.m_fov ) )
 
 2578            m_fovMap[view.m_fov] = fovHandle;
 
 2592            fovHandle = m_fovMap[view.m_fov];
 
 2604                    "/C2W [{:f} {:f} {:f} {:f} {:f} {:f} {:f} {:f} {:f} {:f} {:f} {:f}]\n" 
 2611                    "/C [1.000000 1.000000 1.000000]>>\n" 
 2614                    "/Type /3DLightingScheme\n" 
 2617                    view.m_name, view.m_name, view.m_cameraMatrix[0],
 
 2618                    view.m_cameraMatrix[1],
 
 2619                    view.m_cameraMatrix[2], view.m_cameraMatrix[3], view.m_cameraMatrix[4],
 
 2620                    view.m_cameraMatrix[5], view.m_cameraMatrix[6], view.m_cameraMatrix[7],
 
 2621                    view.m_cameraMatrix[8], view.m_cameraMatrix[9], view.m_cameraMatrix[10],
 
 2622                    view.m_cameraMatrix[11],
 
 2623                    view.m_cameraCenter,
 
 2628        m_viewHandles.push_back( viewHandle );
 
 2643    for( 
int viewHandle : m_viewHandles )
 
 2651                "/Filter /FlateDecode\n" 
 2662    size_t model_stored_size = 0;
 
 2664        wxFFileOutputStream ffos( outputFFile );
 
 2665        wxZlibOutputStream  zos( ffos, wxZ_BEST_COMPRESSION, wxZLIB_ZLIB );
 
 2667        wxFFileInputStream fileStream( aSourcePath );
 
 2668        if( !fileStream.IsOk() )
 
 2670            wxLogError( 
_( 
"Failed to open 3D model file: %s" ), aSourcePath );
 
 2673        zos.Write( fileStream );
 
 2677    model_stored_size -= imgStreamStart; 
 
 2683    fmt::println( 
m_outputFile, 
"{}", (
unsigned) model_stored_size );
 
 2686    outputFFile.Detach(); 
 
 
 2691                                                            float aCameraDistance,
 
 2693                                                            float aPitchDegrees,
 
 2694                                                            float aRollDegrees )
 
 2696    float yRadians = glm::radians( aYawDegrees );
 
 2697    float xRadians = glm::radians( aPitchDegrees );
 
 2698    float zRadians = glm::radians( aRollDegrees );
 
 2701    glm::mat4 rotationMatrix = glm::eulerAngleYXZ( yRadians, xRadians, zRadians );
 
 2705    glm::vec4 cameraOffset = glm::vec4( 0.0f, 0.0f, aCameraDistance, 1.0f );
 
 2708    cameraOffset = rotationMatrix * cameraOffset;
 
 2711    glm::vec3 cameraPosition = glm::vec3(aTargetPosition.
x, aTargetPosition.
y, aTargetPosition.
z)
 
 2712        - glm::vec3( cameraOffset );
 
 2714    std::vector<float> 
result( 12 );
 
 2718    for( 
int col = 0; col < 3; ++col )
 
 2720        for( 
int row = 0; row < 3; ++row )
 
 2722            result[index++] = 
static_cast<float>( rotationMatrix[col][row] );
 
 2727    result[9] = 
static_cast<float>( cameraPosition.x );
 
 2728    result[10] = 
static_cast<float>( cameraPosition.y );
 
 2729    result[11] = 
static_cast<float>( cameraPosition.z );
 
 
void WriteImageSMaskStream(const wxImage &aImage, wxDataOutputStream &aOut)
 
void WriteImageStream(const wxImage &aImage, wxDataOutputStream &aOut, wxColor bg, bool colorMode)
 
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
 
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
 
constexpr const Vec & GetPosition() const
 
constexpr const Vec GetEnd() const
 
constexpr void SetOrigin(const Vec &pos)
 
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
 
constexpr coord_type GetLeft() const
 
constexpr coord_type GetRight() const
 
constexpr void SetEnd(coord_type x, coord_type y)
 
constexpr coord_type GetTop() const
 
constexpr coord_type GetBottom() const
 
static bool IsGotoPageHref(const wxString &aHref, wxString *aDestination=nullptr)
Check if aHref is a valid internal hyperlink.
 
High-level wrapper for evaluating mathematical and string expressions in wxString format.
 
wxString Evaluate(const wxString &aInput)
Main evaluation function - processes input string and evaluates all} expressions.
 
FONT is an abstract base class for both outline and stroke fonts.
 
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
 
virtual bool IsStroke() const
 
virtual bool IsItalic() const
 
virtual bool IsBold() const
 
virtual bool IsOutline() 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).
 
double GetOverbarVerticalPosition(double aGlyphHeight) const
Compute the vertical position of an overbar.
 
Class OUTLINE_FONT implements outline font drawing.
 
A color representation with 4 components: red, green, blue, alpha.
 
std::unique_ptr< NODE > Parse()
 
std::vector< int > m_pageHandles
Handles to the page objects.
 
FILE * m_workFile
Temporary file to construct the stream before zipping.
 
wxString m_parentPageName
 
virtual void ClosePage()
Close the current page in the PDF document (and emit its compressed stream).
 
void emitOutlineNode(OUTLINE_NODE *aNode, int aParentHandle, int aNextNode, int aPrevNode)
Emits a outline item object and recurses into any children.
 
std::map< int, wxImage > m_imageHandles
 
int emitOutline()
Starts emitting the outline object.
 
virtual bool EndPlot() override
 
int startPdfObject(int aHandle=-1)
Open a new PDF object and returns the handle if the parameter is -1.
 
virtual void PlotPoly(const std::vector< VECTOR2I > &aCornerList, FILL_T aFill, int aWidth=USE_DEFAULT_LINE_WIDTH, void *aData=nullptr) override
Polygon plotting for PDF.
 
virtual void Circle(const VECTOR2I &pos, int diametre, FILL_T fill, int width) override
Circle drawing for PDF.
 
virtual void SetCurrentLineWidth(int width, void *aData=nullptr) override
Pen width setting for PDF.
 
int m_streamLengthHandle
Handle to the deferred stream length.
 
void PlotImage(const wxImage &aImage, const VECTOR2I &aPos, double aScaleFactor) override
PDF images are handles as inline, not XObject streams...
 
int m_jsNamesHandle
Handle for Names dictionary with JS.
 
virtual void SetDash(int aLineWidth, LINE_STYLE aLineStyle) override
PDF supports dashed lines.
 
void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs) override
Create a clickable hyperlink menu with a rectangular click area.
 
virtual bool OpenFile(const wxString &aFullFilename) override
Open or create the plot file aFullFilename.
 
int m_fontResDictHandle
Font resource dictionary.
 
virtual void emitSetRGBColor(double r, double g, double b, double a) override
PDF supports colors fully.
 
std::map< int, std::pair< BOX2D, wxString > > m_hyperlinkHandles
Handles for all the hyperlink objects that will be deferred.
 
int m_pageTreeHandle
Handle to the root of the page tree object.
 
virtual void Text(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const EDA_ANGLE &aOrient, const VECTOR2I &aSize, enum GR_TEXT_H_ALIGN_T aH_justify, enum GR_TEXT_V_ALIGN_T aV_justify, int aWidth, bool aItalic, bool aBold, bool aMultilineAllowed, KIFONT::FONT *aFont, const KIFONT::METRICS &aFontMetrics, void *aData=nullptr) override
Draw text with the plotter.
 
int emitGoToAction(int aPageHandle, const VECTOR2I &aBottomLeft, const VECTOR2I &aTopRight)
Emit an action object that instructs a goto coordinates on a page.
 
void closePdfStream()
Finish the current PDF stream (writes the deferred length, too).
 
void Bookmark(const BOX2I &aBox, const wxString &aName, const wxString &aGroupName=wxEmptyString) override
Create a bookmark to a symbol.
 
std::vector< long > m_xrefTable
The PDF xref offset table.
 
void endPlotEmitResources()
 
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width, int aCornerRadius=0) override
Rectangles in PDF.
 
int startPdfStream(int aHandle=-1)
Start a PDF stream (for the page).
 
VECTOR2I renderMarkupNode(const MARKUP::NODE *aNode, const VECTOR2I &aPosition, const VECTOR2I &aBaseSize, const EDA_ANGLE &aOrient, bool aTextMirrored, int aWidth, bool aBaseBold, bool aBaseItalic, KIFONT::FONT *aFont, const KIFONT::METRICS &aFontMetrics, enum GR_TEXT_V_ALIGN_T aV_justify, TEXT_STYLE_FLAGS aTextStyle, std::vector< OVERBAR_INFO > &aOverbars)
Recursively render markup nodes with appropriate styling.
 
virtual void Arc(const VECTOR2D &aCenter, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aAngle, double aRadius, FILL_T aFill, int aWidth) override
The PDF engine can't directly plot arcs so we use polygonization.
 
void HyperlinkBox(const BOX2I &aBox, const wxString &aDestinationURL) override
Create a clickable hyperlink with a rectangular click area.
 
virtual void PenTo(const VECTOR2I &pos, char plume) override
Moveto/lineto primitive, moves the 'pen' to the specified direction.
 
std::map< wxString, std::vector< std::pair< BOX2I, wxString > > > m_bookmarksInPage
 
virtual bool StartPlot(const wxString &aPageNumber) override
The PDF engine supports multiple pages; the first one is opened 'for free' the following are to be cl...
 
virtual void StartPage(const wxString &aPageNumber, const wxString &aPageName=wxEmptyString, const wxString &aParentPageNumber=wxEmptyString, const wxString &aParentPageName=wxEmptyString)
Start a new page in the PDF document.
 
std::unique_ptr< PDF_OUTLINE_FONT_MANAGER > m_outlineFontManager
 
OUTLINE_NODE * addOutlineNode(OUTLINE_NODE *aParent, int aActionHandle, const wxString &aTitle)
Add a new outline node entry.
 
int m_imgResDictHandle
Image resource dictionary.
 
std::string encodeStringForPlotter(const wxString &aUnicode) override
convert a wxString unicode string to a char string compatible with the accepted string PDF format (co...
 
std::unique_ptr< PDF_STROKE_FONT_MANAGER > m_strokeFontManager
 
void Plot3DModel(const wxString &aSourcePath, const std::vector< PDF_3D_VIEW > &a3DViews)
 
std::vector< wxString > m_pageNumbers
List of user-space page numbers for resolving internal hyperlinks.
 
int allocPdfObject()
Allocate a new handle in the table of the PDF object.
 
VECTOR2I renderWord(const wxString &aWord, const VECTOR2I &aPosition, const VECTOR2I &aSize, const EDA_ANGLE &aOrient, bool aTextMirrored, int aWidth, bool aBold, bool aItalic, KIFONT::FONT *aFont, const KIFONT::METRICS &aFontMetrics, enum GR_TEXT_V_ALIGN_T aV_justify, TEXT_STYLE_FLAGS aTextStyle)
Render a single word with the given style parameters.
 
std::string encodeByteString(const std::string &aBytes)
 
void drawOverbars(const std::vector< OVERBAR_INFO > &aOverbars, const EDA_ANGLE &aOrient, const KIFONT::METRICS &aFontMetrics)
Draw overbar lines above text.
 
virtual void SetViewport(const VECTOR2I &aOffset, double aIusPerDecimil, double aScale, bool aMirror) override
PDF can have multiple pages, so SetPageSettings can be called with the outputFile open (but not insid...
 
std::map< int, std::pair< BOX2D, std::vector< wxString > > > m_hyperlinkMenuHandles
 
int m_pageStreamHandle
Handle of the page content object.
 
virtual void PlotText(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const TEXT_ATTRIBUTES &aAttributes, KIFONT::FONT *aFont, const KIFONT::METRICS &aFontMetrics, void *aData=nullptr) override
 
static std::vector< float > CreateC2WMatrixFromAngles(const VECTOR3D &aTargetPosition, float aCameraDistance, float aYawDegrees, float aPitchDegrees, float aRollDegrees)
Generates the camera to world matrix for use with a 3D View.
 
std::vector< std::pair< BOX2I, wxString > > m_hyperlinksInPage
List of loaded hyperlinks in current page.
 
std::unique_ptr< OUTLINE_NODE > m_outlineRoot
Root outline node.
 
std::vector< std::pair< BOX2I, std::vector< wxString > > > m_hyperlinkMenusInPage
 
void closePdfObject()
Close the current PDF object.
 
int m_totalOutlineNodes
Total number of outline nodes.
 
std::vector< VECTOR2D > arcPath(const VECTOR2D &aCenter, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aAngle, double aRadius)
 
const std::string & ResourceName() const
 
std::string BuildDifferencesArray() const
 
double FontBBoxMaxY() const
 
double FontBBoxMinY() const
 
double UnitsPerEm() const
 
double FontBBoxMinX() const
 
void SetToUnicodeHandle(int aHandle)
 
int CharProcsHandle() const
 
std::string BuildWidthsArray() const
 
double FontBBoxMaxX() const
 
void SetFontHandle(int aHandle)
 
int ToUnicodeHandle() const
 
void SetCharProcsHandle(int aHandle)
 
std::string BuildToUnicodeCMap() const
 
std::vector< GLYPH > & Glyphs()
 
double GetDotMarkLenIU(int aLineWidth) const
 
double GetDashGapLenIU(int aLineWidth) const
 
const PROJECT * m_project
 
bool m_mirrorIsHorizontal
 
static const int USE_DEFAULT_LINE_WIDTH
 
void MoveTo(const VECTOR2I &pos)
 
void FinishTo(const VECTOR2I &pos)
 
virtual VECTOR2D userToDeviceCoordinates(const VECTOR2I &aCoordinate)
Modify coordinates according to the orientation, scale factor, and offsets trace.
 
virtual VECTOR2D userToDeviceSize(const VECTOR2I &size)
Modify size according to the plotter scale factors (VECTOR2I version, returns a VECTOR2D).
 
double m_plotScale
Plot scale - chosen by the user (even implicitly with 'fit in a4')
 
FILE * m_outputFile
Output file.
 
void LineTo(const VECTOR2I &pos)
 
static const int DO_NOT_SET_LINE_WIDTH
 
RENDER_SETTINGS * m_renderSettings
 
virtual int GetCurrentLineWidth() const
 
double GetDashMarkLenIU(int aLineWidth) const
 
virtual void SetColor(const COLOR4D &color) override
The SetColor implementation is split with the subclasses: the PSLIKE computes the rgb values,...
 
double plotScaleAdjX
Fine user scale adjust ( = 1.0 if no correction)
 
void computeTextParameters(const VECTOR2I &aPos, const wxString &aText, const EDA_ANGLE &aOrient, const VECTOR2I &aSize, bool aMirror, enum GR_TEXT_H_ALIGN_T aH_justify, enum GR_TEXT_V_ALIGN_T aV_justify, int aWidth, bool aItalic, bool aBold, double *wideningFactor, double *ctm_a, double *ctm_b, double *ctm_c, double *ctm_d, double *ctm_e, double *ctm_f, double *heightFactor)
This is the core for postscript/PDF text alignment.
 
EDA_ANGLE GetCentralAngle() const
Get the "central angle" of the arc - this is the angle at the point of the "pie slice".
 
EDA_ANGLE GetStartAngle() const
 
const VECTOR2I & GetCenter() const
 
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
 
const SHAPE_ARC & Arc(size_t aArc) const
 
ssize_t ArcIndex(size_t aSegment) const
Return the arc index for the given segment index.
 
SEG Segment(int aIndex) const
Return a copy of the aIndex-th segment in the line chain.
 
int SegmentCount() const
Return the number of segments in this line chain.
 
bool IsArcSegment(size_t aSegment) const
 
const SHAPE_LINE_CHAIN Outline() const
 
void SetRadius(int aRadius)
 
GR_TEXT_H_ALIGN_T m_Halign
 
GR_TEXT_V_ALIGN_T m_Valign
 
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
 
std::string substr(size_t pos=0, size_t len=npos) const
 
const wxString ResolveUriByEnvVars(const wxString &aUri, const PROJECT *aProject)
Replace any environment and/or text variables in URIs.
 
@ FILLED_SHAPE
Fill with object color.
 
unsigned int TEXT_STYLE_FLAGS
 
static constexpr double ITALIC_TILT
Tilt factor for italic style (this is the scaling factor on dY relative coordinates to give a tilted ...
 
const wxChar *const tracePdfPlotter
Flag to enable PDF plotter debug tracing.
 
void ignore_unused(const T &)
 
This file contains miscellaneous commonly used macros and functions.
 
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
 
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
 
Plotting engines similar to ps (PostScript, Gerber, svg)
 
wxString NormalizeFileUri(const wxString &aFileUri)
Normalize file path aFileUri to URI convention.
 
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
 
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
 
LINE_STYLE
Dashed line types.
 
bool isSuperscript() const
 
wxString asWxString() const
 
wxString title
Title of outline node.
 
std::vector< OUTLINE_NODE * > children
Ordered list of children.
 
int entryHandle
Allocated handle for this outline entry.
 
OUTLINE_NODE * AddChild(int aActionHandle, const wxString &aTitle, int aEntryHandle)
 
int actionHandle
Handle to action.
 
wxString result
Test unit parsing edge cases and error handling.
 
GR_TEXT_H_ALIGN_T
This is API surface mapped to common.types.HorizontalAlignment.
 
GR_TEXT_V_ALIGN_T
This is API surface mapped to common.types.VertialAlignment.
 
wxLogTrace helper definitions.
 
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
 
VECTOR2< int32_t > VECTOR2I
 
VECTOR2< double > VECTOR2D
 
VECTOR3< double > VECTOR3D