2020-09-23 18:58:13 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2023-07-04 05:57:26 +00:00
|
|
|
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
2020-09-23 18:58:13 +00:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the
|
|
|
|
* Free Software Foundation, either version 3 of the License, or (at your
|
|
|
|
* option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2020-10-20 20:09:13 +00:00
|
|
|
* Plotting engines similar to ps (PostScript, Gerber, svg)
|
2020-09-23 18:58:13 +00:00
|
|
|
*
|
|
|
|
* @file plotters_pslike.h
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2021-08-18 20:38:14 +00:00
|
|
|
#include "plotter.h"
|
2020-09-23 18:58:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
2021-06-07 18:31:53 +00:00
|
|
|
* The PSLIKE_PLOTTER class is an intermediate class to handle common routines for engines
|
|
|
|
* working more or less with the postscript imaging model.
|
2020-09-23 18:58:13 +00:00
|
|
|
*/
|
|
|
|
class PSLIKE_PLOTTER : public PLOTTER
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PSLIKE_PLOTTER() :
|
|
|
|
plotScaleAdjX( 1 ),
|
|
|
|
plotScaleAdjY( 1 ),
|
|
|
|
m_textMode( PLOT_TEXT_MODE::PHANTOM )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* PS and PDF fully implement native text (for the Latin-1 subset)
|
|
|
|
*/
|
|
|
|
virtual void SetTextMode( PLOT_TEXT_MODE mode ) override
|
|
|
|
{
|
|
|
|
if( mode != PLOT_TEXT_MODE::DEFAULT )
|
|
|
|
m_textMode = mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the 'fine' scaling for the postscript engine
|
|
|
|
*/
|
|
|
|
void SetScaleAdjust( double scaleX, double scaleY )
|
|
|
|
{
|
|
|
|
plotScaleAdjX = scaleX;
|
|
|
|
plotScaleAdjY = scaleY;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pad routines are handled with lower level primitives
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void FlashPadCircle( const VECTOR2I& aPadPos, int aDiameter,
|
2020-10-15 23:33:18 +00:00
|
|
|
OUTLINE_MODE aTraceMode, void* aData ) override;
|
2022-01-16 01:06:25 +00:00
|
|
|
virtual void FlashPadOval( const VECTOR2I& aPadPos, const VECTOR2I& aSize,
|
|
|
|
const EDA_ANGLE& aPadOrient, OUTLINE_MODE aTraceMode,
|
|
|
|
void* aData ) override;
|
|
|
|
virtual void FlashPadRect( const VECTOR2I& aPadPos, const VECTOR2I& aSize,
|
|
|
|
const EDA_ANGLE& aPadOrient, OUTLINE_MODE aTraceMode,
|
|
|
|
void* aData ) override;
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void FlashPadRoundRect( const VECTOR2I& aPadPos, const VECTOR2I& aSize,
|
2022-01-16 01:06:25 +00:00
|
|
|
int aCornerRadius, const EDA_ANGLE& aOrient,
|
2020-10-15 23:33:18 +00:00
|
|
|
OUTLINE_MODE aTraceMode, void* aData ) override;
|
2022-01-16 01:06:25 +00:00
|
|
|
virtual void FlashPadCustom( const VECTOR2I& aPadPos, const VECTOR2I& aSize,
|
|
|
|
const EDA_ANGLE& aOrient, SHAPE_POLY_SET* aPolygons,
|
2020-10-15 23:33:18 +00:00
|
|
|
OUTLINE_MODE aTraceMode, void* aData ) override;
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void FlashPadTrapez( const VECTOR2I& aPadPos, const VECTOR2I* aCorners,
|
2022-01-16 01:06:25 +00:00
|
|
|
const EDA_ANGLE& aPadOrient, OUTLINE_MODE aTraceMode,
|
|
|
|
void* aData ) override;
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void FlashRegularPolygon( const VECTOR2I& aShapePos, int aDiameter, int aCornerCount,
|
2022-01-16 01:06:25 +00:00
|
|
|
const EDA_ANGLE& aOrient, OUTLINE_MODE aTraceMode,
|
2021-06-07 18:31:53 +00:00
|
|
|
void* aData ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
|
2020-11-10 13:50:16 +00:00
|
|
|
/**
|
2023-08-06 19:20:53 +00:00
|
|
|
* The SetColor implementation is split with the subclasses: the PSLIKE computes the rgb
|
|
|
|
* values, the subclass emits the operator to actually do it
|
2020-09-23 18:58:13 +00:00
|
|
|
*/
|
2021-06-07 18:31:53 +00:00
|
|
|
virtual void SetColor( const COLOR4D& color ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
|
|
|
|
protected:
|
2021-06-07 18:31:53 +00:00
|
|
|
/**
|
|
|
|
* This is the core for postscript/PDF text alignment.
|
|
|
|
*
|
2023-08-06 19:20:53 +00:00
|
|
|
* It computes the transformation matrix to generate a user space system aligned with the text.
|
|
|
|
* Even the PS uses the concat operator to simplify PDF generation (concat is everything PDF
|
2021-06-07 18:31:53 +00:00
|
|
|
* has to modify the CTM. Lots of parameters, both in and out.
|
|
|
|
*/
|
2021-12-29 19:02:50 +00:00
|
|
|
void computeTextParameters( const VECTOR2I& aPos,
|
2020-09-23 18:58:13 +00:00
|
|
|
const wxString& aText,
|
2021-12-28 22:13:54 +00:00
|
|
|
const EDA_ANGLE& aOrient,
|
2021-12-29 19:02:50 +00:00
|
|
|
const VECTOR2I& aSize,
|
2020-09-23 18:58:13 +00:00
|
|
|
bool aMirror,
|
2021-12-28 22:13:54 +00:00
|
|
|
enum GR_TEXT_H_ALIGN_T aH_justify,
|
|
|
|
enum GR_TEXT_V_ALIGN_T aV_justify,
|
2020-09-23 18:58:13 +00:00
|
|
|
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 );
|
2021-06-07 18:31:53 +00:00
|
|
|
|
2020-09-23 18:58:13 +00:00
|
|
|
/// convert a wxString unicode string to a char string compatible with the accepted
|
|
|
|
/// string plotter format (convert special chars and non ascii7 chars)
|
|
|
|
virtual std::string encodeStringForPlotter( const wxString& aUnicode );
|
|
|
|
|
|
|
|
/// Virtual primitive for emitting the setrgbcolor operator
|
2022-04-08 10:35:52 +00:00
|
|
|
virtual void emitSetRGBColor( double r, double g, double b, double a ) = 0;
|
2020-09-23 18:58:13 +00:00
|
|
|
|
|
|
|
/// Height of the postscript font (from the AFM)
|
|
|
|
static const double postscriptTextAscent; // = 0.718;
|
|
|
|
|
2021-06-07 18:31:53 +00:00
|
|
|
/**
|
2023-08-06 19:20:53 +00:00
|
|
|
* Sister function for the GRTextWidth in gr_text.cpp
|
|
|
|
* Does the same processing (i.e. calculates a text string width) but using postscript metrics
|
|
|
|
* for the Helvetica font (optionally used for PS and PDF plotting
|
2021-06-07 18:31:53 +00:00
|
|
|
*/
|
|
|
|
int returnPostscriptTextWidth( const wxString& aText, int aXSize, bool aItalic, bool aBold );
|
2020-09-23 18:58:13 +00:00
|
|
|
|
|
|
|
/// Fine user scale adjust ( = 1.0 if no correction)
|
|
|
|
double plotScaleAdjX, plotScaleAdjY;
|
|
|
|
|
|
|
|
/// How to draw text
|
|
|
|
PLOT_TEXT_MODE m_textMode;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class PS_PLOTTER : public PSLIKE_PLOTTER
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PS_PLOTTER()
|
|
|
|
{
|
|
|
|
// The phantom plot in postscript is an hack and reportedly
|
|
|
|
// crashes Adobe's own postscript interpreter!
|
|
|
|
m_textMode = PLOT_TEXT_MODE::STROKE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static wxString GetDefaultFileExtension()
|
|
|
|
{
|
|
|
|
return wxString( wxT( "ps" ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual PLOT_FORMAT GetPlotterType() const override
|
|
|
|
{
|
|
|
|
return PLOT_FORMAT::POST;
|
|
|
|
}
|
|
|
|
|
2021-06-07 18:31:53 +00:00
|
|
|
/**
|
|
|
|
* The code within this function (and the CloseFilePS function)
|
|
|
|
* creates postscript files whose contents comply with Adobe's
|
|
|
|
* Document Structuring Convention, as documented by assorted
|
|
|
|
* details described within the following URLs:
|
|
|
|
*
|
|
|
|
* http://en.wikipedia.org/wiki/Document_Structuring_Conventions
|
|
|
|
* http://partners.adobe.com/public/developer/en/ps/5001.DSC_Spec.pdf
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* BBox is the boundary box (position and size of the "client rectangle"
|
|
|
|
* for drawings (page - margins) in mils (0.001 inch)
|
|
|
|
*/
|
2022-08-27 18:14:57 +00:00
|
|
|
virtual bool StartPlot( const wxString& aPageNumber ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
virtual bool EndPlot() override;
|
2021-06-07 18:31:53 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the current line width (in IUs) for the next plot.
|
|
|
|
*/
|
|
|
|
virtual void SetCurrentLineWidth( int width, void* aData = nullptr ) override;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* PostScript supports dashed lines.
|
|
|
|
*/
|
2022-06-28 18:06:17 +00:00
|
|
|
virtual void SetDash( int aLineWidth, PLOT_DASH_TYPE aLineStyle ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void SetViewport( const VECTOR2I& aOffset, double aIusPerDecimil,
|
2021-06-07 18:31:53 +00:00
|
|
|
double aScale, bool aMirror ) override;
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill,
|
2020-09-23 18:58:13 +00:00
|
|
|
int width = USE_DEFAULT_LINE_WIDTH ) override;
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void Circle( const VECTOR2I& pos, int diametre, FILL_T fill,
|
2020-09-23 18:58:13 +00:00
|
|
|
int width = USE_DEFAULT_LINE_WIDTH ) override;
|
2022-01-25 22:33:37 +00:00
|
|
|
virtual void Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR2I& aEnd,
|
|
|
|
FILL_T aFill, int aWidth, int aMaxError ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFill,
|
2021-06-07 18:31:53 +00:00
|
|
|
int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
|
2021-06-07 18:31:53 +00:00
|
|
|
/**
|
|
|
|
* PostScript-likes at the moment are the only plot engines supporting bitmaps.
|
|
|
|
*/
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void PlotImage( const wxImage& aImage, const VECTOR2I& aPos,
|
2020-09-23 18:58:13 +00:00
|
|
|
double aScaleFactor ) override;
|
|
|
|
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void PenTo( const VECTOR2I& pos, char plume ) override;
|
2023-08-06 19:20:53 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
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;
|
2023-02-24 08:44:25 +00:00
|
|
|
|
|
|
|
|
2020-09-23 18:58:13 +00:00
|
|
|
protected:
|
2022-04-08 10:35:52 +00:00
|
|
|
virtual void emitSetRGBColor( double r, double g, double b, double a ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
};
|
|
|
|
|
2020-11-10 13:50:16 +00:00
|
|
|
|
2020-09-23 18:58:13 +00:00
|
|
|
class PDF_PLOTTER : public PSLIKE_PLOTTER
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PDF_PLOTTER() :
|
2022-05-15 12:59:23 +00:00
|
|
|
m_pageTreeHandle( 0 ),
|
|
|
|
m_fontResDictHandle( 0 ),
|
|
|
|
m_pageStreamHandle( 0 ),
|
|
|
|
m_streamLengthHandle( 0 ),
|
2023-02-20 08:16:33 +00:00
|
|
|
m_workFile( nullptr ),
|
|
|
|
m_totalOutlineNodes( 0 )
|
2020-09-23 18:58:13 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual PLOT_FORMAT GetPlotterType() const override
|
|
|
|
{
|
|
|
|
return PLOT_FORMAT::PDF;
|
|
|
|
}
|
|
|
|
|
|
|
|
static wxString GetDefaultFileExtension()
|
|
|
|
{
|
|
|
|
return wxString( wxT( "pdf" ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-06-07 18:31:53 +00:00
|
|
|
* Open or create the plot file aFullFilename.
|
2020-09-23 18:58:13 +00:00
|
|
|
*
|
|
|
|
* The base class open the file in text mode, so we should have this
|
2021-06-07 18:31:53 +00:00
|
|
|
* function overlaid for PDF files, which are binary files.
|
2020-11-10 13:50:16 +00:00
|
|
|
*
|
2021-06-07 18:31:53 +00:00
|
|
|
* @param aFullFilename is the full file name of the file to create.
|
|
|
|
* @return true if success, false if the file cannot be created/opened.
|
2020-09-23 18:58:13 +00:00
|
|
|
*/
|
|
|
|
virtual bool OpenFile( const wxString& aFullFilename ) override;
|
|
|
|
|
2020-11-10 13:50:16 +00:00
|
|
|
/**
|
2021-06-07 18:31:53 +00:00
|
|
|
* The PDF engine supports multiple pages; the first one is opened 'for free' the following
|
|
|
|
* are to be closed and reopened. Between each page parameters can be set.
|
2020-11-10 13:50:16 +00:00
|
|
|
*/
|
2022-08-27 18:14:57 +00:00
|
|
|
virtual bool StartPlot( const wxString& aPageNumber ) override;
|
2022-09-25 02:52:09 +00:00
|
|
|
|
|
|
|
virtual bool StartPlot( const wxString& aPageNumber,
|
|
|
|
const wxString& aPageName = wxEmptyString );
|
|
|
|
|
2020-09-23 18:58:13 +00:00
|
|
|
virtual bool EndPlot() override;
|
2020-11-10 13:50:16 +00:00
|
|
|
|
|
|
|
/**
|
2021-06-07 18:31:53 +00:00
|
|
|
* Start a new page in the PDF document.
|
2020-11-10 13:50:16 +00:00
|
|
|
*/
|
2022-09-25 02:52:09 +00:00
|
|
|
virtual void StartPage( const wxString& aPageNumber, const wxString& aPageName = wxEmptyString );
|
2020-11-10 13:50:16 +00:00
|
|
|
|
|
|
|
/**
|
2021-06-07 18:31:53 +00:00
|
|
|
* Close the current page in the PDF document (and emit its compressed stream).
|
2020-11-10 13:50:16 +00:00
|
|
|
*/
|
2020-09-23 18:58:13 +00:00
|
|
|
virtual void ClosePage();
|
2020-11-10 13:50:16 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Pen width setting for PDF.
|
|
|
|
*
|
|
|
|
* Since the specs *explicitly* says that a 0 width is a bad thing to use (since it
|
|
|
|
* results in 1 pixel traces), we convert such requests to the minimal width (like 1)
|
|
|
|
* Note pen width = 0 is used in plot polygons to plot filled polygons with no outline
|
|
|
|
* thickness. Use in this case pen width = 1 does not actually change the polygon.
|
|
|
|
*/
|
2021-06-07 18:31:53 +00:00
|
|
|
virtual void SetCurrentLineWidth( int width, void* aData = nullptr ) override;
|
2020-11-10 13:50:16 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* PDF supports dashed lines
|
|
|
|
*/
|
2022-06-28 18:06:17 +00:00
|
|
|
virtual void SetDash( int aLineWidth, PLOT_DASH_TYPE aLineStyle ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
|
2020-11-10 13:50:16 +00:00
|
|
|
/**
|
|
|
|
* PDF can have multiple pages, so SetPageSettings can be called
|
|
|
|
* with the outputFile open (but not inside a page stream!)
|
|
|
|
*/
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void SetViewport( const VECTOR2I& aOffset, double aIusPerDecimil,
|
2021-06-07 18:31:53 +00:00
|
|
|
double aScale, bool aMirror ) override;
|
2020-11-10 13:50:16 +00:00
|
|
|
|
|
|
|
/**
|
2021-06-07 18:31:53 +00:00
|
|
|
* Rectangles in PDF. Supported by the native operator.
|
2020-11-10 13:50:16 +00:00
|
|
|
*/
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill,
|
2020-09-23 18:58:13 +00:00
|
|
|
int width = USE_DEFAULT_LINE_WIDTH ) override;
|
2020-11-10 13:50:16 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Circle drawing for PDF. They're approximated by curves, but fill is supported
|
|
|
|
*/
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void Circle( const VECTOR2I& pos, int diametre, FILL_T fill,
|
2020-09-23 18:58:13 +00:00
|
|
|
int width = USE_DEFAULT_LINE_WIDTH ) override;
|
2020-11-10 13:50:16 +00:00
|
|
|
|
|
|
|
/**
|
2022-01-25 22:33:37 +00:00
|
|
|
* The PDF engine can't directly plot arcs so we use polygonization.
|
2020-11-10 13:50:16 +00:00
|
|
|
*/
|
2022-01-25 22:33:37 +00:00
|
|
|
virtual void Arc( const VECTOR2I& aCenter, const VECTOR2I& aStart, const VECTOR2I& aEnd,
|
|
|
|
FILL_T aFill, int aWidth, int aMaxError ) override;
|
|
|
|
|
2023-08-07 01:53:08 +00:00
|
|
|
virtual void Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
|
|
|
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill,
|
|
|
|
int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
|
|
|
|
|
2020-11-10 13:50:16 +00:00
|
|
|
/**
|
|
|
|
* Polygon plotting for PDF. Everything is supported
|
|
|
|
*/
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFill,
|
2021-06-07 18:31:53 +00:00
|
|
|
int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void PenTo( const VECTOR2I& pos, char plume ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
|
2023-08-06 19:20:53 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
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;
|
2023-02-24 08:44:25 +00:00
|
|
|
|
2022-08-27 22:28:31 +00:00
|
|
|
void HyperlinkBox( const BOX2I& aBox, const wxString& aDestinationURL ) override;
|
|
|
|
|
|
|
|
void HyperlinkMenu( const BOX2I& aBox, const std::vector<wxString>& aDestURLs ) override;
|
2022-05-15 19:35:00 +00:00
|
|
|
|
2022-09-25 02:35:20 +00:00
|
|
|
void Bookmark( const BOX2I& aBox, const wxString& aName, const wxString& aGroupName = wxEmptyString ) override;
|
2022-09-25 01:45:48 +00:00
|
|
|
|
2020-11-10 13:50:16 +00:00
|
|
|
/**
|
|
|
|
* PDF images are handles as inline, not XObject streams...
|
|
|
|
*/
|
2022-08-27 22:28:31 +00:00
|
|
|
void PlotImage( const wxImage& aImage, const VECTOR2I& aPos, double aScaleFactor ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
protected:
|
2022-09-25 01:45:48 +00:00
|
|
|
struct OUTLINE_NODE
|
|
|
|
{
|
2022-09-25 12:45:08 +00:00
|
|
|
int actionHandle; ///< Handle to action
|
|
|
|
wxString title; ///< Title of outline node
|
|
|
|
int entryHandle; ///< Allocated handle for this outline entry
|
2022-09-25 01:45:48 +00:00
|
|
|
|
2022-09-25 12:45:08 +00:00
|
|
|
std::vector<OUTLINE_NODE*> children; ///< Ordered list of children
|
|
|
|
|
|
|
|
~OUTLINE_NODE()
|
|
|
|
{
|
|
|
|
std::for_each( children.begin(), children.end(),
|
|
|
|
[]( OUTLINE_NODE* node )
|
|
|
|
{
|
|
|
|
delete node;
|
|
|
|
} );
|
|
|
|
}
|
2022-09-25 01:45:48 +00:00
|
|
|
|
|
|
|
OUTLINE_NODE* AddChild( int aActionHandle, const wxString& aTitle, int aEntryHandle )
|
|
|
|
{
|
|
|
|
OUTLINE_NODE* child = new OUTLINE_NODE
|
|
|
|
{
|
2022-09-25 09:01:25 +00:00
|
|
|
aActionHandle, aTitle, aEntryHandle, {}
|
2022-09-25 01:45:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
children.push_back( child );
|
|
|
|
|
|
|
|
return child;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a new outline node entry
|
|
|
|
*
|
|
|
|
* The PDF object handle is automacially allocated
|
|
|
|
*
|
|
|
|
* @param aParent Parent node to append the new node to
|
|
|
|
* @param aActionHandle The handle of an action that may be performed on click, set to -1 for no action
|
|
|
|
* @param aTitle Title of node to display
|
|
|
|
*/
|
|
|
|
OUTLINE_NODE* addOutlineNode( OUTLINE_NODE* aParent, int aActionHandle,
|
|
|
|
const wxString& aTitle );
|
2022-09-20 16:29:29 +00:00
|
|
|
|
2020-09-23 18:58:13 +00:00
|
|
|
/// convert a wxString unicode string to a char string compatible with the accepted
|
|
|
|
/// string PDF format (convert special chars and non ascii7 chars)
|
|
|
|
std::string encodeStringForPlotter( const wxString& aUnicode ) override;
|
|
|
|
|
2020-11-10 13:50:16 +00:00
|
|
|
/**
|
|
|
|
* PDF supports colors fully. It actually has distinct fill and pen colors,
|
|
|
|
* but we set both at the same time.
|
|
|
|
*
|
|
|
|
* XXX Keeping them divided could result in a minor optimization in
|
|
|
|
* Eeschema filled shapes, but would propagate to all the other plot
|
|
|
|
* engines. Also arcs are filled as pies but only the arc is stroked so
|
|
|
|
* it would be difficult to handle anyway.
|
|
|
|
*/
|
2022-04-08 10:35:52 +00:00
|
|
|
virtual void emitSetRGBColor( double r, double g, double b, double a ) override;
|
2020-11-10 13:50:16 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Allocate a new handle in the table of the PDF object. The
|
|
|
|
* handle must be completed using startPdfObject. It's an in-RAM operation
|
|
|
|
* only, no output is done.
|
|
|
|
*/
|
2020-09-23 18:58:13 +00:00
|
|
|
int allocPdfObject();
|
2020-11-10 13:50:16 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Open a new PDF object and returns the handle if the parameter is -1.
|
|
|
|
* Otherwise fill in the xref entry for the passed object
|
|
|
|
*/
|
2020-09-23 18:58:13 +00:00
|
|
|
int startPdfObject(int handle = -1);
|
2020-11-10 13:50:16 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Close the current PDF object
|
|
|
|
*/
|
2020-09-23 18:58:13 +00:00
|
|
|
void closePdfObject();
|
2020-11-10 13:50:16 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts a PDF stream (for the page). Returns the object handle opened
|
|
|
|
* Pass -1 (default) for a fresh object. Especially from PDF 1.5 streams
|
|
|
|
* can contain a lot of things, but for the moment we only handle page
|
|
|
|
* content.
|
|
|
|
*/
|
2020-09-23 18:58:13 +00:00
|
|
|
int startPdfStream(int handle = -1);
|
2020-11-10 13:50:16 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Finish the current PDF stream (writes the deferred length, too)
|
|
|
|
*/
|
2020-09-23 18:58:13 +00:00
|
|
|
void closePdfStream();
|
2020-11-10 13:50:16 +00:00
|
|
|
|
2022-09-25 01:45:48 +00:00
|
|
|
/**
|
|
|
|
* Starts emitting the outline object
|
|
|
|
*/
|
|
|
|
int emitOutline();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Emits a outline item object and recurses into any children
|
|
|
|
*/
|
|
|
|
void emitOutlineNode( OUTLINE_NODE* aNode, int aParentHandle, int aNextNode, int aPrevNode );
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Emits an action object that instructs a goto coordinates on a page
|
|
|
|
*
|
|
|
|
* @return Generated action handle
|
|
|
|
*/
|
|
|
|
int emitGoToAction( int aPageHandle, const VECTOR2I& aBottomLeft, const VECTOR2I& aTopRight );
|
2022-09-25 03:36:03 +00:00
|
|
|
int emitGoToAction( int aPageHandle );
|
2022-09-25 01:45:48 +00:00
|
|
|
|
2022-05-15 12:59:23 +00:00
|
|
|
int m_pageTreeHandle; ///< Handle to the root of the page tree object
|
|
|
|
int m_fontResDictHandle; ///< Font resource dictionary
|
2023-07-07 16:43:41 +00:00
|
|
|
int m_imgResDictHandle; ///< Image resource dictionary
|
2023-07-04 05:57:26 +00:00
|
|
|
int m_jsNamesHandle; ///< Handle for Names dictionary with JS
|
2022-05-15 12:59:23 +00:00
|
|
|
std::vector<int> m_pageHandles; ///< Handles to the page objects
|
|
|
|
int m_pageStreamHandle; ///< Handle of the page content object
|
|
|
|
int m_streamLengthHandle; ///< Handle to the deferred stream length
|
|
|
|
wxString m_workFilename;
|
2022-09-25 02:52:09 +00:00
|
|
|
wxString m_pageName;
|
2022-05-15 12:59:23 +00:00
|
|
|
FILE* m_workFile; ///< Temporary file to construct the stream before zipping
|
|
|
|
std::vector<long> m_xrefTable; ///< The PDF xref offset table
|
2022-06-23 22:29:48 +00:00
|
|
|
|
2022-08-27 18:14:57 +00:00
|
|
|
///< List of user-space page numbers for resolving internal hyperlinks
|
2022-08-27 22:28:31 +00:00
|
|
|
std::vector<wxString> m_pageNumbers;
|
2022-08-27 18:14:57 +00:00
|
|
|
|
2022-07-03 15:19:55 +00:00
|
|
|
///< List of loaded hyperlinks in current page
|
2022-08-27 22:28:31 +00:00
|
|
|
std::vector<std::pair<BOX2I, wxString>> m_hyperlinksInPage;
|
|
|
|
std::vector<std::pair<BOX2I, std::vector<wxString>>> m_hyperlinkMenusInPage;
|
2022-06-23 22:29:48 +00:00
|
|
|
|
|
|
|
///< Handles for all the hyperlink objects that will be deferred
|
2022-08-27 22:28:31 +00:00
|
|
|
std::map<int, std::pair<BOX2D, wxString>> m_hyperlinkHandles;
|
|
|
|
std::map<int, std::pair<BOX2D, std::vector<wxString>>> m_hyperlinkMenuHandles;
|
2022-09-25 01:45:48 +00:00
|
|
|
|
2022-09-25 02:35:20 +00:00
|
|
|
std::map<wxString, std::vector<std::pair<BOX2I, wxString>>> m_bookmarksInPage;
|
2022-09-25 01:45:48 +00:00
|
|
|
|
2023-07-07 16:43:41 +00:00
|
|
|
std::map<int, wxImage> m_imageHandles;
|
|
|
|
|
2022-09-25 01:45:48 +00:00
|
|
|
std::unique_ptr<OUTLINE_NODE> m_outlineRoot; ///< Root outline node
|
|
|
|
int m_totalOutlineNodes; ///< Total number of outline nodes
|
2020-09-23 18:58:13 +00:00
|
|
|
};
|
|
|
|
|
2020-11-10 13:50:16 +00:00
|
|
|
|
2020-09-23 18:58:13 +00:00
|
|
|
class SVG_PLOTTER : public PSLIKE_PLOTTER
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SVG_PLOTTER();
|
|
|
|
|
|
|
|
static wxString GetDefaultFileExtension()
|
|
|
|
{
|
|
|
|
return wxString( wxT( "svg" ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual PLOT_FORMAT GetPlotterType() const override
|
|
|
|
{
|
|
|
|
return PLOT_FORMAT::SVG;
|
|
|
|
}
|
|
|
|
|
2021-06-07 18:31:53 +00:00
|
|
|
/**
|
|
|
|
* Create SVG file header.
|
|
|
|
*/
|
2022-08-27 18:14:57 +00:00
|
|
|
virtual bool StartPlot( const wxString& aPageNumber ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
virtual bool EndPlot() override;
|
2021-06-07 18:31:53 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the current line width (in IUs) for the next plot.
|
|
|
|
*/
|
|
|
|
virtual void SetCurrentLineWidth( int width, void* aData = nullptr ) override;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SVG supports dashed lines.
|
|
|
|
*/
|
2022-06-28 18:06:17 +00:00
|
|
|
virtual void SetDash( int aLineWidth, PLOT_DASH_TYPE aLineStyle ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void SetViewport( const VECTOR2I& aOffset, double aIusPerDecimil,
|
2021-08-17 17:44:11 +00:00
|
|
|
double aScale, bool aMirror ) override;
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill,
|
2020-09-23 18:58:13 +00:00
|
|
|
int width = USE_DEFAULT_LINE_WIDTH ) override;
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void Circle( const VECTOR2I& pos, int diametre, FILL_T fill,
|
2020-09-23 18:58:13 +00:00
|
|
|
int width = USE_DEFAULT_LINE_WIDTH ) override;
|
|
|
|
|
2023-08-07 01:53:08 +00:00
|
|
|
virtual void Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
|
|
|
|
const EDA_ANGLE& aEndAngle, double aRadius, FILL_T aFill,
|
|
|
|
int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
|
|
|
|
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void BezierCurve( const VECTOR2I& aStart, const VECTOR2I& aControl1,
|
|
|
|
const VECTOR2I& aControl2, const VECTOR2I& aEnd,
|
2020-09-23 18:58:13 +00:00
|
|
|
int aTolerance,
|
|
|
|
int aLineThickness = USE_DEFAULT_LINE_WIDTH ) override;
|
|
|
|
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFill,
|
2021-07-18 23:08:54 +00:00
|
|
|
int aWidth = USE_DEFAULT_LINE_WIDTH, void * aData = nullptr ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
|
2021-06-07 18:31:53 +00:00
|
|
|
/**
|
|
|
|
* PostScript-likes at the moment are the only plot engines supporting bitmaps.
|
|
|
|
*/
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void PlotImage( const wxImage& aImage, const VECTOR2I& aPos,
|
2020-09-23 18:58:13 +00:00
|
|
|
double aScaleFactor ) override;
|
|
|
|
|
2021-12-29 19:02:50 +00:00
|
|
|
virtual void PenTo( const VECTOR2I& pos, char plume ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
|
|
|
|
/**
|
2022-01-28 17:06:47 +00:00
|
|
|
* Select SVG coordinate precision (number of digits needed for 1 mm )
|
|
|
|
* (SVG plotter uses always metric unit)
|
2020-11-10 13:50:16 +00:00
|
|
|
* Should be called only after SetViewport() is called
|
|
|
|
*
|
2022-01-28 17:06:47 +00:00
|
|
|
* @param aPrecision = number of digits in mantissa of coordinate
|
2020-09-23 18:58:13 +00:00
|
|
|
* use a value from 3-6
|
|
|
|
* do not use value > 6 to avoid overflow in PCBNEW
|
|
|
|
* do not use value > 4 to avoid overflow for other parts
|
|
|
|
*/
|
2022-01-28 17:06:47 +00:00
|
|
|
virtual void SetSvgCoordinatesFormat( unsigned aPrecision ) override;
|
2020-09-23 18:58:13 +00:00
|
|
|
|
|
|
|
/**
|
2020-11-10 13:50:16 +00:00
|
|
|
* Calling this function allows one to define the beginning of a group
|
2020-09-23 18:58:13 +00:00
|
|
|
* of drawing items (used in SVG format to separate components)
|
2020-11-10 13:50:16 +00:00
|
|
|
* @param aData should be a string for the SVG ID tag
|
2020-09-23 18:58:13 +00:00
|
|
|
*/
|
|
|
|
virtual void StartBlock( void* aData ) override;
|
|
|
|
|
|
|
|
/**
|
2020-11-10 13:50:16 +00:00
|
|
|
* Calling this function allows one to define the end of a group of drawing
|
2020-09-23 18:58:13 +00:00
|
|
|
* items the group is started by StartBlock()
|
|
|
|
* @param aData should be null
|
|
|
|
*/
|
|
|
|
virtual void EndBlock( void* aData ) override;
|
|
|
|
|
2023-08-06 19:20:53 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
2023-02-24 08:44:25 +00:00
|
|
|
|
2020-09-23 18:58:13 +00:00
|
|
|
protected:
|
2021-06-07 18:31:53 +00:00
|
|
|
/**
|
|
|
|
* Initialize m_pen_rgb_color from reduced values r, g ,b
|
|
|
|
* ( reduced values are 0.0 to 1.0 )
|
|
|
|
*/
|
2022-04-08 10:35:52 +00:00
|
|
|
virtual void emitSetRGBColor( double r, double g, double b, double a ) override;
|
2021-06-07 18:31:53 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Output the string which define pen and brush color, shape, transparency
|
|
|
|
*
|
|
|
|
* @param aIsGroup If false, do not form a new group for the style.
|
|
|
|
* @param aExtraStyle If given, the string will be added into the style string before closing
|
|
|
|
*/
|
2022-06-28 18:06:17 +00:00
|
|
|
void setSVGPlotStyle( int aLineWidth, bool aIsGroup = true,
|
|
|
|
const std::string& aExtraStyle = {} );
|
2021-06-07 18:31:53 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Prepare parameters for setSVGPlotStyle()
|
|
|
|
*/
|
2021-07-18 23:08:54 +00:00
|
|
|
void setFillMode( FILL_T fill );
|
2021-06-07 18:31:53 +00:00
|
|
|
|
2021-07-18 23:08:54 +00:00
|
|
|
FILL_T m_fillMode; // true if the current contour
|
2020-09-23 18:58:13 +00:00
|
|
|
// rect, arc, circle, polygon must be filled
|
2020-11-10 13:50:16 +00:00
|
|
|
long m_pen_rgb_color; // current rgb color value: each color has
|
2020-09-23 18:58:13 +00:00
|
|
|
// a value 0 ... 255, and the 3 colors are
|
|
|
|
// grouped in a 3x8 bits value
|
|
|
|
// (written in hex to svg files)
|
|
|
|
long m_brush_rgb_color; // same as m_pen_rgb_color, used to fill
|
|
|
|
// some contours.
|
2022-04-08 10:35:52 +00:00
|
|
|
double m_brush_alpha;
|
2020-09-23 18:58:13 +00:00
|
|
|
bool m_graphics_changed; // true if a pen/brush parameter is modified
|
2020-11-10 13:50:16 +00:00
|
|
|
// color, pen size, fill mode ...
|
2020-09-23 18:58:13 +00:00
|
|
|
// the new SVG stype must be output on file
|
|
|
|
PLOT_DASH_TYPE m_dashed; // plot line style
|
|
|
|
unsigned m_precision; // How fine the step size is
|
2020-11-10 13:50:16 +00:00
|
|
|
// Use 3-6 (3 means um precision, 6 nm precision) in PcbNew
|
|
|
|
// 3-4 in other modules (avoid values >4 to avoid overflow)
|
2020-09-23 18:58:13 +00:00
|
|
|
// see also comment for m_useInch.
|
|
|
|
};
|