498 lines
20 KiB
C++
498 lines
20 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors.
|
|
*
|
|
* 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/>.
|
|
*/
|
|
|
|
/**
|
|
* Plotting engines similar to ps (PostScript, Gerber, svg)
|
|
*
|
|
* @file plotters_pslike.h
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <vector>
|
|
#include <math/box2.h>
|
|
#include <eda_item.h> // FILL_TYPE
|
|
#include <plotter.h>
|
|
|
|
|
|
/**
|
|
* The PSLIKE_PLOTTER class is an intermediate class to handle common
|
|
* routines for engines working more or less with the postscript imaging
|
|
* model
|
|
*/
|
|
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
|
|
virtual void FlashPadCircle( const wxPoint& aPadPos, int aDiameter,
|
|
OUTLINE_MODE aTraceMode, void* aData ) override;
|
|
virtual void FlashPadOval( const wxPoint& aPadPos, const wxSize& aSize, double aPadOrient,
|
|
OUTLINE_MODE aTraceMode, void* aData ) override;
|
|
virtual void FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize,
|
|
double aPadOrient, OUTLINE_MODE aTraceMode,
|
|
void* aData ) override;
|
|
virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize,
|
|
int aCornerRadius, double aOrient,
|
|
OUTLINE_MODE aTraceMode, void* aData ) override;
|
|
virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, double aOrient,
|
|
SHAPE_POLY_SET* aPolygons,
|
|
OUTLINE_MODE aTraceMode, void* aData ) override;
|
|
virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
|
|
double aPadOrient, OUTLINE_MODE aTraceMode, void* aData ) override;
|
|
virtual void FlashRegularPolygon( const wxPoint& aShapePos, int aDiameter, int aCornerCount,
|
|
double aOrient, OUTLINE_MODE aTraceMode, void* aData ) override;
|
|
|
|
/**
|
|
* The SetColor implementation is split with the subclasses:
|
|
* The PSLIKE computes the rgb values, the subclass emits the
|
|
* operator to actually do it
|
|
*/
|
|
virtual void SetColor( COLOR4D color ) override;
|
|
|
|
protected:
|
|
void computeTextParameters( const wxPoint& aPos,
|
|
const wxString& aText,
|
|
int aOrient,
|
|
const wxSize& aSize,
|
|
bool aMirror,
|
|
enum EDA_TEXT_HJUSTIFY_T aH_justify,
|
|
enum EDA_TEXT_VJUSTIFY_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 );
|
|
void postscriptOverlinePositions( const wxString& aText, int aXSize,
|
|
bool aItalic, bool aBold,
|
|
std::vector<int> *pos_pairs );
|
|
|
|
/// 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
|
|
virtual void emitSetRGBColor( double r, double g, double b ) = 0;
|
|
|
|
/// Height of the postscript font (from the AFM)
|
|
static const double postscriptTextAscent; // = 0.718;
|
|
|
|
int returnPostscriptTextWidth( const wxString& aText, int aXSize,
|
|
bool aItalic, bool aBold );
|
|
|
|
/// 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;
|
|
}
|
|
|
|
virtual bool StartPlot() override;
|
|
virtual bool EndPlot() override;
|
|
virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override;
|
|
virtual void SetDash( PLOT_DASH_TYPE dashed ) override;
|
|
|
|
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
|
|
double aScale, bool aMirror ) override;
|
|
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill,
|
|
int width = USE_DEFAULT_LINE_WIDTH ) override;
|
|
virtual void Circle( const wxPoint& pos, int diametre, FILL_TYPE fill,
|
|
int width = USE_DEFAULT_LINE_WIDTH ) override;
|
|
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
|
|
int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ) override;
|
|
|
|
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList,
|
|
FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH,
|
|
void * aData = NULL ) override;
|
|
|
|
virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos,
|
|
double aScaleFactor ) override;
|
|
|
|
virtual void PenTo( const wxPoint& pos, char plume ) override;
|
|
virtual void Text( const wxPoint& aPos,
|
|
const COLOR4D aColor,
|
|
const wxString& aText,
|
|
double aOrient,
|
|
const wxSize& aSize,
|
|
enum EDA_TEXT_HJUSTIFY_T aH_justify,
|
|
enum EDA_TEXT_VJUSTIFY_T aV_justify,
|
|
int aWidth,
|
|
bool aItalic,
|
|
bool aBold,
|
|
bool aMultilineAllowed = false,
|
|
void* aData = NULL ) override;
|
|
protected:
|
|
virtual void emitSetRGBColor( double r, double g, double b ) override;
|
|
};
|
|
|
|
|
|
class PDF_PLOTTER : public PSLIKE_PLOTTER
|
|
{
|
|
public:
|
|
PDF_PLOTTER() :
|
|
pageTreeHandle( 0 ),
|
|
fontResDictHandle( 0 ),
|
|
pageStreamHandle( 0 ),
|
|
streamLengthHandle( 0 ),
|
|
workFile( nullptr )
|
|
{
|
|
}
|
|
|
|
virtual PLOT_FORMAT GetPlotterType() const override
|
|
{
|
|
return PLOT_FORMAT::PDF;
|
|
}
|
|
|
|
static wxString GetDefaultFileExtension()
|
|
{
|
|
return wxString( wxT( "pdf" ) );
|
|
}
|
|
|
|
/**
|
|
* Open or create the plot file aFullFilename
|
|
*
|
|
* The base class open the file in text mode, so we should have this
|
|
* function overlaid for PDF files, which are binary files
|
|
*
|
|
* @param aFullFilename = the full file name of the file to create
|
|
* @return true if success, false if the file cannot be created/opened
|
|
*/
|
|
virtual bool OpenFile( const wxString& aFullFilename ) override;
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
virtual bool StartPlot() override;
|
|
virtual bool EndPlot() override;
|
|
|
|
/**
|
|
* Starts a new page in the PDF document
|
|
*/
|
|
virtual void StartPage();
|
|
|
|
/**
|
|
* Close the current page in the PDF document (and emit its compressed stream)
|
|
*/
|
|
virtual void ClosePage();
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override;
|
|
|
|
/**
|
|
* PDF supports dashed lines
|
|
*/
|
|
virtual void SetDash( PLOT_DASH_TYPE dashed ) override;
|
|
|
|
/**
|
|
* PDF can have multiple pages, so SetPageSettings can be called
|
|
* with the outputFile open (but not inside a page stream!)
|
|
*/
|
|
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
|
|
double aScale, bool aMirror ) override;
|
|
|
|
/**
|
|
* Rectangles in PDF. Supported by the native operator
|
|
*/
|
|
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill,
|
|
int width = USE_DEFAULT_LINE_WIDTH ) override;
|
|
|
|
/**
|
|
* Circle drawing for PDF. They're approximated by curves, but fill is supported
|
|
*/
|
|
virtual void Circle( const wxPoint& pos, int diametre, FILL_TYPE fill,
|
|
int width = USE_DEFAULT_LINE_WIDTH ) override;
|
|
|
|
/**
|
|
* The PDF engine can't directly plot arcs, it uses the base emulation.
|
|
* So no filled arcs (not a great loss... )
|
|
*/
|
|
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
|
|
int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ) override;
|
|
|
|
/**
|
|
* Polygon plotting for PDF. Everything is supported
|
|
*/
|
|
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList,
|
|
FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH,
|
|
void * aData = NULL ) override;
|
|
|
|
virtual void PenTo( const wxPoint& pos, char plume ) override;
|
|
|
|
virtual void Text( const wxPoint& aPos,
|
|
const COLOR4D aColor,
|
|
const wxString& aText,
|
|
double aOrient,
|
|
const wxSize& aSize,
|
|
enum EDA_TEXT_HJUSTIFY_T aH_justify,
|
|
enum EDA_TEXT_VJUSTIFY_T aV_justify,
|
|
int aWidth,
|
|
bool aItalic,
|
|
bool aBold,
|
|
bool aMultilineAllowed = false,
|
|
void* aData = NULL ) override;
|
|
/**
|
|
* PDF images are handles as inline, not XObject streams...
|
|
*/
|
|
virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos,
|
|
double aScaleFactor ) override;
|
|
|
|
|
|
protected:
|
|
/// 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;
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
virtual void emitSetRGBColor( double r, double g, double b ) override;
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
int allocPdfObject();
|
|
|
|
/**
|
|
* Open a new PDF object and returns the handle if the parameter is -1.
|
|
* Otherwise fill in the xref entry for the passed object
|
|
*/
|
|
int startPdfObject(int handle = -1);
|
|
|
|
/**
|
|
* Close the current PDF object
|
|
*/
|
|
void closePdfObject();
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
int startPdfStream(int handle = -1);
|
|
|
|
/**
|
|
* Finish the current PDF stream (writes the deferred length, too)
|
|
*/
|
|
void closePdfStream();
|
|
|
|
int pageTreeHandle; /// Handle to the root of the page tree object
|
|
int fontResDictHandle; /// Font resource dictionary
|
|
std::vector<int> pageHandles;/// Handles to the page objects
|
|
int pageStreamHandle; /// Handle of the page content object
|
|
int streamLengthHandle; /// Handle to the deferred stream length
|
|
wxString workFilename;
|
|
FILE* workFile; /// Temporary file to construct the stream before zipping
|
|
std::vector<long> xrefTable; /// The PDF xref offset table
|
|
};
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
virtual void SetColor( COLOR4D color ) override;
|
|
virtual bool StartPlot() override;
|
|
virtual bool EndPlot() override;
|
|
virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override;
|
|
virtual void SetDash( PLOT_DASH_TYPE dashed ) override;
|
|
|
|
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
|
|
double aScale, bool aMirror ) override;
|
|
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill,
|
|
int width = USE_DEFAULT_LINE_WIDTH ) override;
|
|
virtual void Circle( const wxPoint& pos, int diametre, FILL_TYPE fill,
|
|
int width = USE_DEFAULT_LINE_WIDTH ) override;
|
|
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
|
|
int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ) override;
|
|
|
|
virtual void BezierCurve( const wxPoint& aStart, const wxPoint& aControl1,
|
|
const wxPoint& aControl2, const wxPoint& aEnd,
|
|
int aTolerance,
|
|
int aLineThickness = USE_DEFAULT_LINE_WIDTH ) override;
|
|
|
|
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList,
|
|
FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH,
|
|
void * aData = NULL ) override;
|
|
|
|
virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos,
|
|
double aScaleFactor ) override;
|
|
|
|
virtual void PenTo( const wxPoint& pos, char plume ) override;
|
|
|
|
/**
|
|
* Select SVG step size (number of digits needed for 1 mm or 1 inch )
|
|
*
|
|
* Should be called only after SetViewport() is called
|
|
*
|
|
* @param aResolution = number of digits in mantissa of coordinate
|
|
* 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
|
|
* @param aUseInches = true to use inches, false to use mm (default)
|
|
*/
|
|
virtual void SetSvgCoordinatesFormat( unsigned aResolution, bool aUseInches = false ) override;
|
|
|
|
/**
|
|
* Calling this function allows one to define the beginning of a group
|
|
* of drawing items (used in SVG format to separate components)
|
|
* @param aData should be a string for the SVG ID tag
|
|
*/
|
|
virtual void StartBlock( void* aData ) override;
|
|
|
|
/**
|
|
* Calling this function allows one to define the end of a group of drawing
|
|
* items the group is started by StartBlock()
|
|
* @param aData should be null
|
|
*/
|
|
virtual void EndBlock( void* aData ) override;
|
|
|
|
virtual void Text( const wxPoint& aPos,
|
|
const COLOR4D aColor,
|
|
const wxString& aText,
|
|
double aOrient,
|
|
const wxSize& aSize,
|
|
enum EDA_TEXT_HJUSTIFY_T aH_justify,
|
|
enum EDA_TEXT_VJUSTIFY_T aV_justify,
|
|
int aWidth,
|
|
bool aItalic,
|
|
bool aBold,
|
|
bool aMultilineAllowed = false,
|
|
void* aData = NULL ) override;
|
|
|
|
protected:
|
|
FILL_TYPE m_fillMode; // true if the current contour
|
|
// rect, arc, circle, polygon must be filled
|
|
long m_pen_rgb_color; // current rgb color value: each color has
|
|
// 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.
|
|
bool m_graphics_changed; // true if a pen/brush parameter is modified
|
|
// color, pen size, fill mode ...
|
|
// the new SVG stype must be output on file
|
|
PLOT_DASH_TYPE m_dashed; // plot line style
|
|
bool m_useInch; // is 0 if the step size is 10**-n*mm
|
|
// is 1 if the step size is 10**-n*inch
|
|
// Where n is given from m_precision
|
|
unsigned m_precision; // How fine the step size is
|
|
// Use 3-6 (3 means um precision, 6 nm precision) in PcbNew
|
|
// 3-4 in other modules (avoid values >4 to avoid overflow)
|
|
// see also comment for m_useInch.
|
|
|
|
/**
|
|
* Initialize m_pen_rgb_color from reduced values r, g ,b
|
|
* ( reduced values are 0.0 to 1.0 )
|
|
*/
|
|
virtual void emitSetRGBColor( double r, double g, double b ) override;
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
void setSVGPlotStyle( bool aIsGroup = true, const std::string& aExtraStyle = {} );
|
|
|
|
/**
|
|
* Prepare parameters for setSVGPlotStyle()
|
|
*/
|
|
void setFillMode( FILL_TYPE fill );
|
|
};
|