34#include <wx/filename.h>
35#include <wx/mstream.h>
36#include <wx/zstream.h>
37#include <wx/wfstream.h>
38#include <wx/datstrm.h>
39#include <wx/tokenzr.h>
49#include <fmt/format.h>
50#include <fmt/chrono.h>
51#include <fmt/ranges.h>
65 bool is_ascii7 =
true;
67 for(
size_t ii = 0; ii < aText.Len(); ii++ )
69 if( aText[ii] >= 0x7F )
80 for(
unsigned ii = 0; ii < aText.Len(); ii++ )
82 unsigned int code = aText[ii];
105 for(
size_t ii = 0; ii < aText.Len(); ii++ )
107 unsigned int code = aText[ii];
108 result += fmt::format(
"{:04X}", code);
135 double aScale,
bool aMirror )
162 wxASSERT_MSG( aWidth > 0,
"Plotter called to set negative pen width" );
179 r = ( r * a ) + ( 1 - a );
180 g = ( g * a ) + ( 1 - a );
181 b = ( b * a ) + ( 1 - a );
184 fmt::println(
m_workFile,
"{:g} {:g} {:g} rg {:g} {:g} {:g} RG", r, g, b, r, g, b );
194 case LINE_STYLE::DASH:
200 case LINE_STYLE::DOT:
206 case LINE_STYLE::DASHDOT:
207 fmt::println(
m_workFile,
"[{} {} {} {}] 0 d",
214 case LINE_STYLE::DASHDOTDOT:
215 fmt::println(
m_workFile,
"[{} {} {} {} {} {}] 0 d",
234 if( fill == FILL_T::NO_FILL && width == 0 )
241 if( size.
x == 0 && size.
y == 0 )
253 std::vector<VECTOR2I> cornerList;
255 cornerList.emplace_back( p1.
x, p1.
y );
256 cornerList.emplace_back( p2.
x, p1.
y );
257 cornerList.emplace_back( p2.
x, p2.
y );
258 cornerList.emplace_back( p1.
x, p2.
y );
259 cornerList.emplace_back( p1.
x, p1.
y );
261 PlotPoly( cornerList, fill, width,
nullptr );
271 if( fill == FILL_T::NO_FILL )
274 paintOp = width > 0 ?
'B' :
'f';
276 fmt::println(
m_workFile,
"{:g} {:g} {:g} {:g} re {}",
289 if( aFill == FILL_T::NO_FILL && width == 0 )
300 aFill = FILL_T::FILLED_SHAPE;
310 double magic =
radius * 0.551784;
315 "{:g} {:g} {:g} {:g} {:g} {:g} c "
316 "{:g} {:g} {:g} {:g} {:g} {:g} c "
317 "{:g} {:g} {:g} {:g} {:g} {:g} c "
318 "{:g} {:g} {:g} {:g} {:g} {:g} c {}",
321 pos_dev.
x -
radius, pos_dev.
y + magic,
322 pos_dev.
x - magic, pos_dev.
y +
radius,
325 pos_dev.
x + magic, pos_dev.
y +
radius,
326 pos_dev.
x +
radius, pos_dev.
y + magic,
329 pos_dev.
x +
radius, pos_dev.
y - magic,
330 pos_dev.
x + magic, pos_dev.
y -
radius,
333 pos_dev.
x - magic, pos_dev.
y -
radius,
334 pos_dev.
x -
radius, pos_dev.
y - magic,
337 aFill == FILL_T::NO_FILL ?
's' :
'b' );
359 EDA_ANGLE endAngle = startAngle - aAngle;
364 if( startAngle > endAngle )
365 std::swap( startAngle, endAngle );
368 start.
x =
KiROUND( aCenter.
x + aRadius * ( -startAngle ).Cos() );
369 start.
y =
KiROUND( aCenter.
y + aRadius * ( -startAngle ).Sin() );
371 fmt::print(
m_workFile,
"{:g} {:g} m ", pos_dev.
x, pos_dev.
y );
378 fmt::print(
m_workFile,
"{:g} {:g} l ", pos_dev.
x, pos_dev.
y );
381 end.
x =
KiROUND( aCenter.
x + aRadius * ( -endAngle ).Cos() );
382 end.
y =
KiROUND( aCenter.
y + aRadius * ( -endAngle ).Sin() );
384 fmt::print(
m_workFile,
"{:g} {:g} l ", pos_dev.
x, pos_dev.
y );
388 if( aFill == FILL_T::NO_FILL )
395 fmt::println(
m_workFile,
"{:g} {:g} l b", pos_dev.
x, pos_dev.
y );
405 if( aCornerList.size() <= 1 )
408 if( aFill == FILL_T::NO_FILL && aWidth == 0 )
414 fmt::println(
m_workFile,
"{:f} {:f} m", pos.
x, pos.
y );
416 for(
unsigned ii = 1; ii < aCornerList.size(); ii++ )
419 fmt::println(
m_workFile,
"{:f} {:f} l", pos.
x, pos.
y );
423 if( aFill == FILL_T::NO_FILL )
425 else if( aWidth == 0 )
455 plume ==
'D' ?
'l' :
'm' );
466 VECTOR2I pix_size( aImage.GetWidth(), aImage.GetHeight() );
469 VECTOR2D drawsize( aScaleFactor * pix_size.
x, aScaleFactor * pix_size.
y );
472 VECTOR2I start( aPos.
x - drawsize.
x / 2, aPos.
y + drawsize.
y / 2 );
476 auto findHandleForImage = [&](
const wxImage& aCurrImage ) ->
int
480 if(
image.IsSameAs( aCurrImage ) )
483 if(
image.GetWidth() != aCurrImage.GetWidth() )
486 if(
image.GetHeight() != aCurrImage.GetHeight() )
489 if(
image.GetType() != aCurrImage.GetType() )
492 if(
image.HasAlpha() != aCurrImage.HasAlpha() )
495 if(
image.HasMask() != aCurrImage.HasMask()
496 ||
image.GetMaskRed() != aCurrImage.GetMaskRed()
497 ||
image.GetMaskGreen() != aCurrImage.GetMaskGreen()
498 ||
image.GetMaskBlue() != aCurrImage.GetMaskBlue() )
501 int pixCount =
image.GetWidth() *
image.GetHeight();
503 if( memcmp(
image.GetData(), aCurrImage.GetData(), pixCount * 3 ) != 0 )
506 if(
image.HasAlpha() && memcmp(
image.GetAlpha(), aCurrImage.GetAlpha(), pixCount ) != 0 )
515 int imgHandle = findHandleForImage( aImage );
517 if( imgHandle == -1 )
533 fmt::println(
m_workFile,
"q {:g} 0 0 {:g} {:g} {:g} cm",
539 fmt::println(
m_workFile,
"/Im{} Do", imgHandle );
586 "<< /Length {} 0 R >>\n"
593 "<< /Length {} 0 R /Filter /FlateDecode >>\n"
620 unsigned char *inbuf =
new unsigned char[stream_len];
622 int rc = fread( inbuf, 1, stream_len,
m_workFile );
623 wxASSERT( rc == stream_len );
635 out_count = stream_len;
641 wxMemoryOutputStream memos(
nullptr, std::max( 2000l, stream_len ) ) ;
651 wxZlibOutputStream zos( memos, wxZ_BEST_COMPRESSION, wxZLIB_ZLIB );
653 zos.Write( inbuf, stream_len );
656 wxStreamBuffer* sb = memos.GetOutputStreamBuffer();
658 out_count = sb->Tell();
659 fwrite( sb->GetBufferStart(), 1, out_count,
m_outputFile );
674 const wxString& aParentPageNumber,
const wxString& aParentPageName )
680 m_pageName = aPageName.IsEmpty() ? wxString::Format(
_(
"Page %s" ),
682 : wxString::Format(
_(
"%s (Page %s)" ),
687 : wxString::Format(
_(
"%s (Page %s)" ),
710 "{:g} 0 0 {:g} 0 0 cm 1 J 1 j 0 0 0 rg 0 0 0 RG {:g} w",
717void WriteImageStream(
const wxImage& aImage, wxDataOutputStream& aOut, wxColor bg,
bool colorMode )
719 int w = aImage.GetWidth();
720 int h = aImage.GetHeight();
722 for(
int y = 0; y < h; y++ )
724 for(
int x = 0; x < w; x++ )
726 unsigned char r = aImage.GetRed( x, y ) & 0xFF;
727 unsigned char g = aImage.GetGreen( x, y ) & 0xFF;
728 unsigned char b = aImage.GetBlue( x, y ) & 0xFF;
730 if( aImage.HasMask() )
732 if( r == aImage.GetMaskRed() && g == aImage.GetMaskGreen()
733 && b == aImage.GetMaskBlue() )
750 unsigned char grey =
KiROUND( r * 0.2126 + g * 0.7152 + b * 0.0722 );
761 int w = aImage.GetWidth();
762 int h = aImage.GetHeight();
764 if( aImage.HasMask() )
766 for(
int y = 0; y < h; y++ )
768 for(
int x = 0; x < w; x++ )
770 unsigned char a = 255;
771 unsigned char r = aImage.GetRed( x, y );
772 unsigned char g = aImage.GetGreen( x, y );
773 unsigned char b = aImage.GetBlue( x, y );
775 if( r == aImage.GetMaskRed() && g == aImage.GetMaskGreen()
776 && b == aImage.GetMaskBlue() )
785 else if( aImage.HasAlpha() )
788 aOut.Write8( aImage.GetAlpha(), size );
807 const double PTsPERMIL = 0.072;
810 auto iuToPdfUserSpace =
823 retval.
x = ( psPaperSize.
x - pos.
x );
832 std::vector<int> annotHandles;
838 const BOX2I& box = linkPair.first;
839 const wxString& url = linkPair.second;
846 userSpaceBox.
SetEnd( topRight );
855 const BOX2I& box = menuPair.first;
856 const std::vector<wxString>& urls = menuPair.second;
863 userSpaceBox.
SetEnd( topRight );
870 int annot3DHandle = -1;
875 annotHandles.push_back( annot3DHandle );
879 int hyperLinkArrayHandle = -1;
882 if( annotHandles.size() > 0 )
889 for(
int handle : annotHandles )
912 " /ProcSet [/PDF /Text /ImageC /ImageB]\n"
914 " /XObject {} 0 R >>\n"
915 "/MediaBox [0 0 {:g} {:g}]\n"
916 "/Contents {} 0 R\n",
920 if( annotHandles.size() > 0 )
921 fmt::print(
m_outputFile,
"/Annots {} 0 R", hyperLinkArrayHandle );
934 "/Rect [0 0 {:g} {:g}]\n"
935 "/NM (3D Annotation)\n"
938 "/3DA<</A/PO/D/PC/TB true/NP true>>\n"
956 std::stack<OUTLINE_NODE*> nodes;
959 while( !nodes.empty() )
985 for(
const std::pair<BOX2I, wxString>& bookmarkPair : groupVector )
987 const BOX2I& box = bookmarkPair.first;
988 const wxString& ref = bookmarkPair.second;
993 actionHandle =
emitGoToAction( pageHandle, bottomLeft, topRight );
998 std::sort( groupOutlineNode->
children.begin(), groupOutlineNode->
children.end(),
1001 return a->title < b->title;
1014 return StartPlot( aPageNumber, wxEmptyString );
1037 fmt::print(
m_outputFile,
"%PDF-1.5\n%\200\201\202\203\n" );
1065 "<</S /GoTo /D [{} 0 R /FitR {} {} {} {}]\n"
1075 return actionHandle;
1085 "<</S /GoTo /D [{} 0 R /Fit]\n"
1091 return actionHandle;
1099 int prevHandle = -1;
1100 int nextHandle = -1;
1102 for( std::vector<OUTLINE_NODE*>::iterator it = node->
children.begin();
1105 if( it >= node->
children.end() - 1 )
1111 nextHandle = ( *( it + 1 ) )->entryHandle;
1116 prevHandle = ( *it )->entryHandle;
1120 if( parentHandle != -1 )
1133 fmt::println(
m_outputFile,
"/Next {} 0 R", nextNode );
1138 fmt::println(
m_outputFile,
"/Prev {} 0 R", prevNode );
1143 int32_t count = -1 *
static_cast<int32_t
>( node->
children.size() );
1161 const wxString& aTitle )
1182 "<< /Type /Outlines\n"
1210 {
"/Helvetica",
"/KicadFont", 0 },
1211 {
"/Helvetica-Oblique",
"/KicadFontI", 0 },
1212 {
"/Helvetica-Bold",
"/KicadFontB", 0 },
1213 {
"/Helvetica-BoldOblique",
"/KicadFontBI", 0 }
1219 for(
int i = 0; i < 4; i++ )
1225 " /Subtype /Type1\n"
1226 " /Encoding /WinAnsiEncoding\n"
1228 fontdefs[i].psname );
1236 for(
int i = 0; i < 4; i++ )
1239 fontdefs[i].rsname, fontdefs[i].font_handle );
1251 fmt::print(
m_outputFile,
" /Im{} {} 0 R\n", imgHandle, imgHandle );
1272 "/BitsPerComponent 8\n"
1276 "/Filter /FlateDecode\n"
1283 if( smaskHandle != -1 )
1284 fmt::println(
m_outputFile,
"/SMask {} 0 R", smaskHandle );
1292 wxFFileOutputStream ffos( outputFFile );
1293 wxZlibOutputStream zos( ffos, wxZ_BEST_COMPRESSION, wxZLIB_ZLIB );
1294 wxDataOutputStream dos( zos );
1300 long imgStreamSize = ftell(
m_outputFile ) - imgStreamStart;
1309 if( smaskHandle != -1 )
1319 "/BitsPerComponent 8\n"
1320 "/ColorSpace /DeviceGray\n"
1324 "/Filter /FlateDecode\n"
1335 wxFFileOutputStream ffos( outputFFile );
1336 wxZlibOutputStream zos( ffos, wxZ_BEST_COMPRESSION, wxZLIB_ZLIB );
1337 wxDataOutputStream dos( zos );
1342 long smaskStreamSize = ftell(
m_outputFile ) - smaskStreamStart;
1348 fmt::println(
m_outputFile,
"{}", (
unsigned) smaskStreamSize );
1352 outputFFile.Detach();
1357 BOX2D box = linkPair.first;
1358 wxString url = linkPair.second;
1366 "/Rect [{:g} {:g} {:g} {:g}]\n"
1367 "/Border [16 16 0]\n",
1373 wxString pageNumber;
1374 bool pageFound =
false;
1383 "/Dest [{} 0 R /FitB]\n"
1395 fmt::print(
m_outputFile,
"/A << /Type /Action /S /NOP >>\n"
1405 "/A << /Type /Action /S /URI /URI {} >>\n"
1415 const BOX2D& box = menuPair.first;
1416 const std::vector<wxString>& urls = menuPair.second;
1417 wxString js = wxT(
"ShM([\n" );
1419 for(
const wxString& url : urls )
1421 if( url.StartsWith(
"!" ) )
1423 wxString
property = url.AfterFirst(
'!' );
1425 if( property.Find(
"http:" ) >= 0 )
1427 wxString href =
property.substr( property.Find(
"http:" ) );
1432 js += wxString::Format( wxT(
"[\"%s\", \"%s\"],\n" ),
1436 else if( property.Find(
"https:" ) >= 0 )
1438 wxString href =
property.substr( property.Find(
"https:" ) );
1443 js += wxString::Format( wxT(
"[\"%s\", \"%s\"],\n" ),
1447 else if( property.Find(
"file:" ) >= 0 )
1449 wxString href =
property.substr( property.Find(
"file:" ) );
1456 js += wxString::Format( wxT(
"[\"%s\", \"%s\"],\n" ),
1462 js += wxString::Format( wxT(
"[\"%s\"],\n" ),
1466 else if( url.StartsWith(
"#" ) )
1468 wxString pageNumber = url.AfterFirst(
'#' );
1474 wxString menuText = wxString::Format(
_(
"Show Page %s" ), pageNumber );
1476 js += wxString::Format( wxT(
"[\"%s\", \"#%d\"],\n" ),
1478 static_cast<int>( ii ) );
1483 else if( url.StartsWith(
"http:" ) || url.StartsWith(
"https:" )
1484 || url.StartsWith(
"file:" ) )
1486 wxString href = url;
1491 if( url.StartsWith(
"file:" ) )
1494 wxString menuText = wxString::Format(
_(
"Open %s" ), href );
1496 js += wxString::Format( wxT(
"[\"%s\", \"%s\"],\n" ),
1510 "/Rect [{:g} {:g} {:g} {:g}]\n"
1511 "/Border [16 16 0]\n",
1515 "/A << /Type /Action /S /JavaScript /JS {} >>\n"
1526function ShM(aEntries) {
1528 for (var i in aEntries) {
1530 cName: aEntries[i][0],
1531 cReturn: aEntries[i][1]
1535 var cChoice = app.popUpMenuEx.apply(app, aParams);
1536 if (cChoice != null && cChoice.substring(0, 1) == '#') this.pageNum = parseInt(cChoice.slice(1));
1537 else if (cChoice != null && cChoice.substring(0, 4) == 'http') app.launchURL(cChoice);
1538 else if (cChoice != null && cChoice.substring(0, 4) == 'file') app.openDoc(cChoice.substring(7));
1545 " [ (JSInit) << /Type /Action /S /JavaScript /JS {} >> ]\n"
1588 std::string dt = fmt::format(
"D:{:%Y:%m:%d:%H:%M:%S}", fmt::localtime( std::time(
nullptr ) ) );
1599 "/Producer (KiCad PDF)\n"
1600 "/CreationDate ({})\n"
1615 int outlineHandle = -1;
1624 if( outlineHandle > 0 )
1631 "/PageMode /UseOutlines\n"
1632 "/Outlines {} 0 R\n"
1634 "/PageLayout /SinglePage\n"
1647 "/PageMode /UseNone\n"
1648 "/PageLayout /SinglePage\n"
1662 "0000000000 65535 f \n",
1665 for(
unsigned i = 1; i <
m_xrefTable.size(); i++ )
1673 "<< /Size {} /Root {} 0 R /Info {} 0 R >>\n"
1691 const wxString& aText,
1699 bool aMultilineAllowed,
1705 if( aSize.
x == 0 || aSize.
y == 0 )
1710 int render_mode = 3;
1713 const char *fontname = aItalic ? ( aBold ?
"/KicadFontBI" :
"/KicadFontI" )
1714 : ( aBold ?
"/KicadFontB" :
"/KicadFont" );
1717 double ctm_a, ctm_b, ctm_c, ctm_d, ctm_e, ctm_f;
1718 double wideningFactor, heightFactor;
1721 bool textMirrored = aSize.
x < 0;
1724 aWidth, aItalic, aBold, &wideningFactor, &ctm_a, &ctm_b, &ctm_c, &ctm_d,
1725 &ctm_e, &ctm_f, &heightFactor );
1730 wxStringTokenizer str_tok( aText,
" ", wxTOKEN_RET_DELIMS );
1758 while( str_tok.HasMoreTokens() )
1760 wxString word = str_tok.GetNextToken();
1764 &ctm_a, &ctm_b, &ctm_c, &ctm_d, &ctm_e, &ctm_f, &heightFactor );
1769 aBold, aItalic, aFontMetrics ).
x, 0 );
1778 if( word.Trim(
false ).Trim(
true ).empty() )
1785 fmt::print(
m_workFile,
"q {:f} {:f} {:f} {:f} {:f} {:f} cm BT {} {:g} Tf {} Tr {:g} Tz ",
1786 ctm_a, ctm_b, ctm_c, ctm_d, ctm_e, ctm_f,
1790 wideningFactor * 100 );
1793 fmt::println(
m_workFile,
"{} Tj ET", txt_pdf );
1799 PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, aWidth, aItalic,
1800 aBold, aMultilineAllowed, aFont, aFontMetrics );
1806 const wxString& aText,
1815 if( size.
x == 0 || size.
y == 0 )
1840 const wxString &aGroupName )
1843 m_bookmarksInPage[aGroupName].push_back( std::make_pair( aLocation, aSymbolReference ) );
1848 const std::vector<PDF_3D_VIEW>& a3DViews )
1850 std::map<float, int> m_fovMap;
1851 std::vector<int> m_viewHandles;
1856 if( !m_fovMap.contains( view.m_fov ) )
1859 m_fovMap[view.m_fov] = fovHandle;
1873 fovHandle = m_fovMap[view.m_fov];
1885 "/C2W [{:f} {:f} {:f} {:f} {:f} {:f} {:f} {:f} {:f} {:f} {:f} {:f}]\n"
1892 "/C [1.000000 1.000000 1.000000]>>\n"
1895 "/Type /3DLightingScheme\n"
1898 view.m_name, view.m_name, view.m_cameraMatrix[0],
1899 view.m_cameraMatrix[1],
1900 view.m_cameraMatrix[2], view.m_cameraMatrix[3], view.m_cameraMatrix[4],
1901 view.m_cameraMatrix[5], view.m_cameraMatrix[6], view.m_cameraMatrix[7],
1902 view.m_cameraMatrix[8], view.m_cameraMatrix[9], view.m_cameraMatrix[10],
1903 view.m_cameraMatrix[11],
1904 view.m_cameraCenter,
1909 m_viewHandles.push_back( viewHandle );
1924 for(
int viewHandle : m_viewHandles )
1932 "/Filter /FlateDecode\n"
1943 size_t model_stored_size = 0;
1945 wxFFileOutputStream ffos( outputFFile );
1946 wxZlibOutputStream zos( ffos, wxZ_BEST_COMPRESSION, wxZLIB_ZLIB );
1948 wxFFileInputStream fileStream( aSourcePath );
1949 if( !fileStream.IsOk() )
1951 wxLogError(
_(
"Failed to open 3D model file: %s" ), aSourcePath );
1954 zos.Write( fileStream );
1958 model_stored_size -= imgStreamStart;
1964 fmt::println(
m_outputFile,
"{}", (
unsigned) model_stored_size );
1967 outputFFile.Detach();
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 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.
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)
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).
A color representation with 4 components: red, green, blue, alpha.
wxColour ToColour() const
int GetDefaultPenWidth() const
virtual const COLOR4D & GetBackgroundColor() const =0
Return current background color settings.
const VECTOR2D & GetSizeMils() const
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()
int startPdfStream(int aHandle=-1)
Start a PDF stream (for the page).
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.
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...
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.
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
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width) override
Rectangles in PDF.
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.
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.
static const int DO_NOT_SET_LINE_WIDTH
RENDER_SETTINGS * m_renderSettings
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 aPenWidth, bool aItalic, bool aBold, bool aMultilineAllowed, KIFONT::FONT *aFont, const KIFONT::METRICS &aFontMetrics, void *aData=nullptr)
Draw text with the plotter.
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.
GR_TEXT_H_ALIGN_T m_Halign
GR_TEXT_V_ALIGN_T m_Valign
const wxString ResolveUriByEnvVars(const wxString &aUri, const PROJECT *aProject)
Replace any environment and/or text variables in URIs.
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:...
LINE_STYLE
Dashed line types.
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.
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.
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