Add missing files
This commit is contained in:
parent
61acac28e1
commit
684d98ecca
|
@ -0,0 +1,774 @@
|
|||
/**
|
||||
* @file common_plotPDF_functions.cpp
|
||||
* @brief Kicad: Common plot PDF Routines
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <appl_wxstruct.h>
|
||||
#include <trigo.h>
|
||||
#include <wxstruct.h>
|
||||
#include <base_struct.h>
|
||||
#include <common.h>
|
||||
#include <plot_common.h>
|
||||
#include <macros.h>
|
||||
#include <kicad_string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
void PDF_PLOTTER::SetPageSettings( const PAGE_INFO& aPageSettings )
|
||||
{
|
||||
wxASSERT( !workFile );
|
||||
pageInfo = aPageSettings;
|
||||
}
|
||||
|
||||
void PDF_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
|
||||
double aScale, bool aMirror )
|
||||
{
|
||||
wxASSERT( !workFile );
|
||||
plotMirror = aMirror;
|
||||
plotOffset = aOffset;
|
||||
plotScale = aScale;
|
||||
|
||||
// The CTM is set to 1 user unit per decimil
|
||||
iuPerDeviceUnit = 1.0 / aIusPerDecimil;
|
||||
|
||||
/* The paper size in this engined is handled page by page
|
||||
Look in the StartPage function */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 default width (like -1)
|
||||
*/
|
||||
void PDF_PLOTTER::SetCurrentLineWidth( int width )
|
||||
{
|
||||
wxASSERT( workFile );
|
||||
int pen_width;
|
||||
|
||||
if( width > 0 )
|
||||
pen_width = width;
|
||||
else
|
||||
pen_width = defaultPenWidth;
|
||||
|
||||
if( pen_width != currentPenWidth )
|
||||
fprintf( workFile, "%g w\n",
|
||||
userToDeviceSize( pen_width ) );
|
||||
|
||||
currentPenWidth = pen_width;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void PDF_PLOTTER::emitSetRGBColor( double r, double g, double b )
|
||||
{
|
||||
wxASSERT( workFile );
|
||||
fprintf( workFile, "%g %g %g rg %g %g %g RG\n",
|
||||
r, g, b, r, g, b );
|
||||
}
|
||||
|
||||
/**
|
||||
* PDF supports dashed lines
|
||||
*/
|
||||
void PDF_PLOTTER::SetDash( bool dashed )
|
||||
{
|
||||
wxASSERT( workFile );
|
||||
if( dashed )
|
||||
fputs( "[200] 100 d\n", workFile );
|
||||
else
|
||||
fputs( "[] 0 d\n", workFile );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Rectangles in PDF. Supported by the native operator
|
||||
*/
|
||||
void PDF_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width )
|
||||
{
|
||||
wxASSERT( workFile );
|
||||
DPOINT p1_dev = userToDeviceCoordinates( p1 );
|
||||
DPOINT p2_dev = userToDeviceCoordinates( p2 );
|
||||
|
||||
SetCurrentLineWidth( width );
|
||||
fprintf( workFile, "%g %g %g %g re %c\n", p1_dev.x, p1_dev.y,
|
||||
p2_dev.x - p1_dev.x, p2_dev.y - p1_dev.y,
|
||||
fill == NO_FILL ? 'S' : 'B' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Circle drawing for PDF. They're approximated by curves, but fill is supported
|
||||
*/
|
||||
void PDF_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_T aFill, int width )
|
||||
{
|
||||
wxASSERT( workFile );
|
||||
DPOINT pos_dev = userToDeviceCoordinates( pos );
|
||||
double radius = userToDeviceSize( diametre / 2.0 );
|
||||
|
||||
/* OK. Here's a trick. PDF doesn't support circles or circular angles, that's
|
||||
a fact. You'll have to do with cubic beziers. These *can't* represent
|
||||
circular arcs (NURBS can, beziers don't). But there is a widely known
|
||||
approximation which is really good */
|
||||
|
||||
SetCurrentLineWidth( width );
|
||||
double magic = radius * 0.551784; // You don't want to know where this come from
|
||||
|
||||
// This is the convex hull for the bezier approximated circle
|
||||
fprintf( workFile, "%g %g m "
|
||||
"%g %g %g %g %g %g c "
|
||||
"%g %g %g %g %g %g c "
|
||||
"%g %g %g %g %g %g c "
|
||||
"%g %g %g %g %g %g c %c\n",
|
||||
pos_dev.x - radius, pos_dev.y,
|
||||
|
||||
pos_dev.x - radius, pos_dev.y + magic,
|
||||
pos_dev.x - magic, pos_dev.y + radius,
|
||||
pos_dev.x, pos_dev.y + radius,
|
||||
|
||||
pos_dev.x + magic, pos_dev.y + radius,
|
||||
pos_dev.x + radius, pos_dev.y + magic,
|
||||
pos_dev.x + radius, pos_dev.y,
|
||||
|
||||
pos_dev.x + radius, pos_dev.y - magic,
|
||||
pos_dev.x + magic, pos_dev.y - radius,
|
||||
pos_dev.x, pos_dev.y - radius,
|
||||
|
||||
pos_dev.x - magic, pos_dev.y - radius,
|
||||
pos_dev.x - radius, pos_dev.y - magic,
|
||||
pos_dev.x - radius, pos_dev.y,
|
||||
|
||||
aFill == NO_FILL ? 's' : 'b' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The PDF engine can't directly plot arcs, it uses the base emulation.
|
||||
* So no filled arcs (not a great loss... )
|
||||
*/
|
||||
void PDF_PLOTTER::Arc( const wxPoint& centre, int StAngle, int EndAngle, int radius,
|
||||
FILL_T fill, int width )
|
||||
{
|
||||
wxASSERT( workFile );
|
||||
if( radius <= 0 )
|
||||
return;
|
||||
|
||||
/* Arcs are not so easily approximated by beziers (in the general case),
|
||||
so we approximate them in the old way */
|
||||
wxPoint start, end;
|
||||
const int delta = 50; // increment (in 0.1 degrees) to draw circles
|
||||
|
||||
if( StAngle > EndAngle )
|
||||
EXCHG( StAngle, EndAngle );
|
||||
|
||||
SetCurrentLineWidth( width );
|
||||
|
||||
// Usual trig arc plotting routine...
|
||||
double alpha = DEG2RAD( StAngle / 10.0 );
|
||||
start.x = centre.x + (int) ( radius * cos( -alpha ) );
|
||||
start.y = centre.y + (int) ( radius * sin( -alpha ) );
|
||||
DPOINT pos_dev = userToDeviceCoordinates( start );
|
||||
fprintf( workFile, "%g %g m ", pos_dev.x, pos_dev.y );
|
||||
for( int ii = StAngle + delta; ii < EndAngle; ii += delta )
|
||||
{
|
||||
alpha = DEG2RAD( ii / 10.0 );
|
||||
end.x = centre.x + (int) ( radius * cos( -alpha ) );
|
||||
end.y = centre.y + (int) ( radius * sin( -alpha ) );
|
||||
pos_dev = userToDeviceCoordinates( end );
|
||||
fprintf( workFile, "%g %g l ", pos_dev.x, pos_dev.y );
|
||||
}
|
||||
|
||||
alpha = DEG2RAD( EndAngle / 10.0 );
|
||||
end.x = centre.x + (int) ( radius * cos( -alpha ) );
|
||||
end.y = centre.y + (int) ( radius * sin( -alpha ) );
|
||||
pos_dev = userToDeviceCoordinates( end );
|
||||
fprintf( workFile, "%g %g l ", pos_dev.x, pos_dev.y );
|
||||
|
||||
// The arc is drawn... if not filled we stroke it, otherwise we finish
|
||||
// closing the pie at the center
|
||||
if( fill == NO_FILL )
|
||||
{
|
||||
fputs( "S\n", workFile );
|
||||
}
|
||||
else
|
||||
{
|
||||
pos_dev = userToDeviceCoordinates( centre );
|
||||
fprintf( workFile, "%g %g l b\n", pos_dev.x, pos_dev.y );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Polygon plotting for PDF. Everything is supported
|
||||
*/
|
||||
void PDF_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList,
|
||||
FILL_T aFill, int aWidth )
|
||||
{
|
||||
wxASSERT( workFile );
|
||||
if( aCornerList.size() <= 1 )
|
||||
return;
|
||||
|
||||
SetCurrentLineWidth( aWidth );
|
||||
|
||||
DPOINT pos = userToDeviceCoordinates( aCornerList[0] );
|
||||
fprintf( workFile, "%g %g m\n", pos.x, pos.y );
|
||||
|
||||
for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
|
||||
{
|
||||
pos = userToDeviceCoordinates( aCornerList[ii] );
|
||||
fprintf( workFile, "%g %g l\n", pos.x, pos.y );
|
||||
}
|
||||
|
||||
// Close path and stroke(/fill)
|
||||
fprintf( workFile, "%c\n", aFill == NO_FILL ? 'S' : 'b' );
|
||||
}
|
||||
|
||||
|
||||
void PDF_PLOTTER::PenTo( const wxPoint& pos, char plume )
|
||||
{
|
||||
wxASSERT( workFile );
|
||||
if( plume == 'Z' )
|
||||
{
|
||||
if( penState != 'Z' )
|
||||
{
|
||||
fputs( "S\n", workFile );
|
||||
penState = 'Z';
|
||||
penLastpos.x = -1;
|
||||
penLastpos.y = -1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( penState != plume || pos != penLastpos )
|
||||
{
|
||||
DPOINT pos_dev = userToDeviceCoordinates( pos );
|
||||
fprintf( workFile, "%g %g %c\n",
|
||||
pos_dev.x, pos_dev.y,
|
||||
( plume=='D' ) ? 'l' : 'm' );
|
||||
}
|
||||
penState = plume;
|
||||
penLastpos = pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* PDF images are handles as inline, not XObject streams...
|
||||
*/
|
||||
void PDF_PLOTTER::PlotImage( const wxImage & aImage, const wxPoint& aPos,
|
||||
double aScaleFactor )
|
||||
{
|
||||
wxASSERT( workFile );
|
||||
wxSize pix_size( aImage.GetWidth(), aImage.GetHeight() );
|
||||
|
||||
// Requested size (in IUs)
|
||||
DPOINT drawsize( aScaleFactor * pix_size.x,
|
||||
aScaleFactor * pix_size.y );
|
||||
|
||||
// calculate the bitmap start position
|
||||
wxPoint start( aPos.x - drawsize.x / 2,
|
||||
aPos.y + drawsize.y / 2);
|
||||
|
||||
DPOINT dev_start = userToDeviceCoordinates( start );
|
||||
|
||||
/* PDF has an uhm... simplified coordinate system handling. There is
|
||||
*one* operator to do everything (the PS concat equivalent). At least
|
||||
they kept the matrix stack to save restore environments. Also images
|
||||
are always emitted at the origin with a size of 1x1 user units.
|
||||
What we need to do is:
|
||||
1) save the CTM end estabilish the new one
|
||||
2) plot the image
|
||||
3) restore the CTM
|
||||
4) profit
|
||||
*/
|
||||
fprintf( workFile, "q %g 0 0 %g %g %g cm\n", // Step 1
|
||||
userToDeviceSize( drawsize.x ),
|
||||
userToDeviceSize( drawsize.y ),
|
||||
dev_start.x, dev_start.y );
|
||||
|
||||
/* An inline image is a cross between a dictionary and a stream.
|
||||
A real ugly construct (compared with the elegance of the PDF
|
||||
format). Also it accepts some 'abbreviations', which is stupid
|
||||
since the content stream is usually compressed anyway... */
|
||||
fprintf( workFile,
|
||||
"BI\n"
|
||||
" /BPC 8\n"
|
||||
" /CS %s\n"
|
||||
" /W %d\n"
|
||||
" /H %d\n"
|
||||
"ID\n", colorMode ? "/RGB" : "/G", pix_size.x, pix_size.y );
|
||||
|
||||
/* Here comes the stream (in binary!). I *could* have hex or ascii84
|
||||
encoded it, but who cares? I'll go through zlib anyway */
|
||||
for( int y = 0; y < pix_size.y; y++ )
|
||||
{
|
||||
for( int x = 0; x < pix_size.x; x++ )
|
||||
{
|
||||
unsigned char r = aImage.GetRed( x, y ) & 0xFF;
|
||||
unsigned char g = aImage.GetGreen( x, y ) & 0xFF;
|
||||
unsigned char b = aImage.GetBlue( x, y ) & 0xFF;
|
||||
// As usual these days, stdio buffering has to suffeeeeerrrr
|
||||
if( colorMode )
|
||||
{
|
||||
putc( r, workFile );
|
||||
putc( g, workFile );
|
||||
putc( b, workFile );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Grayscale conversion
|
||||
putc( (r + g + b) / 3, workFile );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fputs( "EI Q\n", workFile ); // Finish step 2 and do step 3
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 PDF_PLOTTER::allocPdfObject()
|
||||
{
|
||||
xrefTable.push_back( 0 );
|
||||
return xrefTable.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 PDF_PLOTTER::startPdfObject(int handle)
|
||||
{
|
||||
wxASSERT( outputFile );
|
||||
wxASSERT( !workFile );
|
||||
if( handle < 0)
|
||||
handle = allocPdfObject();
|
||||
|
||||
xrefTable[handle] = ftell( outputFile );
|
||||
fprintf( outputFile, "%d 0 obj\n", handle );
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close the current PDF object
|
||||
*/
|
||||
void PDF_PLOTTER::closePdfObject()
|
||||
{
|
||||
wxASSERT( outputFile );
|
||||
wxASSERT( !workFile );
|
||||
fputs( "endobj\n", outputFile );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 PDF_PLOTTER::startPdfStream(int handle)
|
||||
{
|
||||
wxASSERT( outputFile );
|
||||
wxASSERT( !workFile );
|
||||
handle = startPdfObject( handle );
|
||||
|
||||
// This is guaranteed to be handle+1 but needs to be allocated since
|
||||
// you could allocate more object during stream preparation
|
||||
streamLengthHandle = allocPdfObject();
|
||||
fprintf( outputFile,
|
||||
"<< /Length %d 0 R /Filter /FlateDecode >>\n" // Length is deferred
|
||||
"stream\n", handle + 1 );
|
||||
|
||||
// Open a temporary file to accumulate the stream
|
||||
workFilename = filename + wxT(".tmp");
|
||||
workFile = wxFopen( workFilename, wxT( "w+b" ));
|
||||
wxASSERT( workFile );
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finish the current PDF stream (writes the deferred length, too)
|
||||
* XXX the compression code is not very elegant... is slurps the
|
||||
* whole stream in RAM, allocates an output buffer of the same size
|
||||
* and try to FLATE it. Asserts if it couldn't... enhancements are
|
||||
* welcome but for now it simply works
|
||||
*/
|
||||
void PDF_PLOTTER::closePdfStream()
|
||||
{
|
||||
wxASSERT( workFile );
|
||||
|
||||
// Ask for the stream length
|
||||
int stream_len = ftell( workFile );
|
||||
|
||||
// Now we do a trick: rewind the file, read in the page stream and FLATE it
|
||||
fseek( workFile, 0, SEEK_SET );
|
||||
unsigned char *inbuf = new unsigned char[stream_len];
|
||||
|
||||
int rc = fread( inbuf, 1, stream_len, workFile );
|
||||
wxASSERT( rc == stream_len );
|
||||
|
||||
// We have done with the temporary file, junk it
|
||||
fclose( workFile );
|
||||
workFile = 0;
|
||||
::wxRemoveFile( workFilename );
|
||||
|
||||
z_stream zstrm;
|
||||
zstrm.zalloc = NULL;
|
||||
zstrm.zfree = NULL;
|
||||
zstrm.opaque = NULL;
|
||||
|
||||
/* Somewhat standard parameters to compress in FLATE. The PDF spec is
|
||||
misleading, it says it wants a FLATE stream but it really want a ZLIB
|
||||
stream! (a FLATE stream would be generated with -15 instead of 15) */
|
||||
rc = deflateInit2( &zstrm, Z_BEST_COMPRESSION, Z_DEFLATED, 15,
|
||||
8, Z_DEFAULT_STRATEGY );
|
||||
wxASSERT( rc == Z_OK );
|
||||
zstrm.avail_in = stream_len;
|
||||
zstrm.next_in = inbuf;
|
||||
|
||||
// PDF streams are very compactable, we trust it doesn't expand
|
||||
unsigned char *outbuf = new unsigned char[stream_len];
|
||||
zstrm.avail_out = stream_len;
|
||||
zstrm.next_out = outbuf;
|
||||
|
||||
// Do a full in-memory compaction
|
||||
rc = deflate( &zstrm, Z_FINISH );
|
||||
wxASSERT( rc == Z_STREAM_END );
|
||||
|
||||
// Now write the packed stream on the main file and free memory
|
||||
stream_len -= zstrm.avail_out;
|
||||
fwrite( outbuf, 1, stream_len, outputFile );
|
||||
|
||||
delete[] inbuf;
|
||||
delete[] outbuf;
|
||||
fputs( "endstream\n", outputFile );
|
||||
closePdfObject();
|
||||
|
||||
// Writing the deferred length as an indirect object
|
||||
startPdfObject( streamLengthHandle );
|
||||
fprintf( outputFile, "%d\n", stream_len );
|
||||
closePdfObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new page in the PDF document
|
||||
*/
|
||||
void PDF_PLOTTER::StartPage()
|
||||
{
|
||||
wxASSERT( outputFile );
|
||||
wxASSERT( !workFile );
|
||||
|
||||
// Compute the paper size in IUs
|
||||
paperSize = pageInfo.GetSizeMils();
|
||||
paperSize.x *= 10.0 / iuPerDeviceUnit;
|
||||
paperSize.y *= 10.0 / iuPerDeviceUnit;
|
||||
SetDefaultLineWidth( 100 / iuPerDeviceUnit ); // arbitrary default
|
||||
|
||||
// Open the content stream; the page object will go later
|
||||
pageStreamHandle = startPdfStream();
|
||||
|
||||
/* Now, until ClosePage *everything* must be wrote in workFile, to be
|
||||
compressed later in closePdfStream */
|
||||
|
||||
// Default graphic settings (coordinate system, default color and line style)
|
||||
fprintf( workFile,
|
||||
"%g 0 0 %g 0 0 cm 1 J 1 j 0 0 0 rg 0 0 0 RG %g w\n",
|
||||
0.0072 * plotScaleAdjX, 0.0072 * plotScaleAdjY,
|
||||
userToDeviceSize( defaultPenWidth ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the current page in the PDF document (and emit its compressed stream)
|
||||
*/
|
||||
void PDF_PLOTTER::ClosePage()
|
||||
{
|
||||
wxASSERT( workFile );
|
||||
|
||||
// Close the page stream (and compress it)
|
||||
closePdfStream();
|
||||
|
||||
// Emit the page object and put it in the page list for later
|
||||
pageHandles.push_back( startPdfObject() );
|
||||
|
||||
/* Page size is in 1/72 of inch (default user space units)
|
||||
Works like the bbox in postscript but there is no need for
|
||||
swapping the sizes, since PDF doesn't require a portrait page.
|
||||
We use the MediaBox but PDF has lots of other less used boxes
|
||||
to use */
|
||||
|
||||
const double BIGPTsPERMIL = 0.072;
|
||||
wxSize psPaperSize = pageInfo.GetSizeMils();
|
||||
|
||||
fprintf( outputFile,
|
||||
"<<\n"
|
||||
"/Type /Page\n"
|
||||
"/Parent %d 0 R\n"
|
||||
"/Resources <<\n"
|
||||
" /ProcSet [/PDF /Text /ImageC /ImageB]\n"
|
||||
" /Font %d 0 R >>\n"
|
||||
"/MediaBox [0 0 %d %d]\n"
|
||||
"/Contents %d 0 R\n"
|
||||
">>\n",
|
||||
pageTreeHandle,
|
||||
fontResDictHandle,
|
||||
int( ceil( psPaperSize.x * BIGPTsPERMIL ) ),
|
||||
int( ceil( psPaperSize.y * BIGPTsPERMIL ) ),
|
||||
pageStreamHandle );
|
||||
closePdfObject();
|
||||
|
||||
// Mark the page stream as idle
|
||||
pageStreamHandle = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
bool PDF_PLOTTER::StartPlot( FILE* fout )
|
||||
{
|
||||
wxASSERT( !outputFile );
|
||||
|
||||
outputFile = fout;
|
||||
|
||||
// First things first: the customary null object
|
||||
xrefTable.clear();
|
||||
xrefTable.push_back( 0 );
|
||||
|
||||
/* The header (that's easy!). The second line is binary junk required
|
||||
to make the file binary from the beginning (the important thing is
|
||||
that they must have the bit 7 set) */
|
||||
fputs( "%PDF-1.5\n%\200\201\202\203\n", outputFile );
|
||||
|
||||
/* Allocate an entry for the page tree root, it will go in every page
|
||||
parent entry */
|
||||
pageTreeHandle = allocPdfObject();
|
||||
|
||||
/* In the same way, the font resource dictionary is used by every page
|
||||
(it *could* be inherited via the Pages tree */
|
||||
fontResDictHandle = allocPdfObject();
|
||||
|
||||
/* Now, the PDF is read from the end, (more or less)... so we start
|
||||
with the page stream for page 1. Other more important stuff is written
|
||||
at the end */
|
||||
StartPage();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PDF_PLOTTER::EndPlot()
|
||||
{
|
||||
wxASSERT( outputFile );
|
||||
|
||||
// Close the current page (often the only one)
|
||||
ClosePage();
|
||||
|
||||
/* We need to declare the resources we're using (fonts in particular)
|
||||
The useful standard one is the Helvetica family. Adding external fonts
|
||||
is *very* involved! */
|
||||
struct {
|
||||
const char *psname;
|
||||
const char *rsname;
|
||||
int font_handle;
|
||||
} fontdefs[4] = {
|
||||
{ "/Helvetica", "/KicadFont", 0 },
|
||||
{ "/Helvetica-Oblique", "/KicadFontI", 0 },
|
||||
{ "/Helvetica-Bold", "/KicadFontB", 0 },
|
||||
{ "/Helvetica-BoldOblique", "/KicadFontBI", 0 }
|
||||
};
|
||||
|
||||
/* Declare the font resources. Since they're builtin fonts, no descriptors (yay!)
|
||||
We'll need metrics anyway to do any aligment (these are in the shared with
|
||||
the postscript engine) */
|
||||
for( int i = 0; i < 4; i++ )
|
||||
{
|
||||
fontdefs[i].font_handle = startPdfObject();
|
||||
fprintf( outputFile,
|
||||
"<< /BaseFont %s\n"
|
||||
" /Type /Font\n"
|
||||
" /Subtype /Type1\n"
|
||||
|
||||
/* Adobe is so Mac-based that the nearest thing to Latin1 is
|
||||
the Windows ANSI encoding! */
|
||||
" /Encoding /WinAnsiEncoding\n"
|
||||
">>\n",
|
||||
fontdefs[i].psname );
|
||||
closePdfObject();
|
||||
}
|
||||
|
||||
// Named font dictionary (was allocated, now we emit it)
|
||||
startPdfObject( fontResDictHandle );
|
||||
fputs( "<<\n", outputFile );
|
||||
for( int i = 0; i < 4; i++ )
|
||||
{
|
||||
fprintf( outputFile, " %s %d 0 R\n",
|
||||
fontdefs[i].rsname, fontdefs[i].font_handle );
|
||||
}
|
||||
fputs( ">>\n", outputFile );
|
||||
closePdfObject();
|
||||
|
||||
/* The page tree: it's a B-tree but luckily we only have few pages!
|
||||
So we use just an array... The handle was allocated at the beginning,
|
||||
now we instantiate the corresponding object */
|
||||
startPdfObject( pageTreeHandle );
|
||||
fputs( "<<\n"
|
||||
"/Type /Pages\n"
|
||||
"/Kids [\n", outputFile );
|
||||
|
||||
for( unsigned i = 0; i < pageHandles.size(); i++ )
|
||||
fprintf( outputFile, "%d 0 R\n", pageHandles[i] );
|
||||
|
||||
fprintf( outputFile,
|
||||
"]\n"
|
||||
"/Count %ld\n"
|
||||
">>\n", (long) pageHandles.size() );
|
||||
closePdfObject();
|
||||
|
||||
|
||||
// The info dictionary
|
||||
int infoDictHandle = startPdfObject();
|
||||
char date_buf[250];
|
||||
time_t ltime = time( NULL );
|
||||
strftime( date_buf, 250, "D:%Y%m%d%H%M%S",
|
||||
localtime( <ime ) );
|
||||
fprintf( outputFile,
|
||||
"<<\n"
|
||||
"/Producer (KiCAD PDF)\n"
|
||||
"/CreationDate (%s)\n"
|
||||
"/Creator (%s)\n"
|
||||
"/Title (%s)\n"
|
||||
"/Trapped false\n",
|
||||
date_buf,
|
||||
TO_UTF8( creator ),
|
||||
TO_UTF8( filename ) );
|
||||
|
||||
fputs( ">>\n", outputFile );
|
||||
closePdfObject();
|
||||
|
||||
// The catalog, at last
|
||||
int catalogHandle = startPdfObject();
|
||||
fprintf( outputFile,
|
||||
"<<\n"
|
||||
"/Type /Catalog\n"
|
||||
"/Pages %d 0 R\n"
|
||||
"/Version /1.5\n"
|
||||
"/PageMode /UseNone\n"
|
||||
"/PageLayout /SinglePage\n"
|
||||
">>\n", pageTreeHandle );
|
||||
closePdfObject();
|
||||
|
||||
/* Emit the xref table (format is crucial to the byte, each entry must
|
||||
be 20 bytes long, and object zero must be done in that way). Also
|
||||
the offset must be kept along for the trailer */
|
||||
long xref_start = ftell( outputFile );
|
||||
fprintf( outputFile,
|
||||
"xref\n"
|
||||
"0 %ld\n"
|
||||
"0000000000 65535 f \n", (long) xrefTable.size() );
|
||||
for( unsigned i = 1; i < xrefTable.size(); i++ )
|
||||
{
|
||||
fprintf( outputFile, "%010ld 00000 n \n", xrefTable[i] );
|
||||
}
|
||||
|
||||
// Done the xref, go for the trailer
|
||||
fprintf( outputFile,
|
||||
"trailer\n"
|
||||
"<< /Size %lu /Root %d 0 R /Info %d 0 R >>\n"
|
||||
"startxref\n"
|
||||
"%ld\n" // The offset we saved before
|
||||
"%%EOF\n",
|
||||
(unsigned long) xrefTable.size(), catalogHandle, infoDictHandle, xref_start );
|
||||
|
||||
fclose( outputFile );
|
||||
outputFile = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PDF_PLOTTER::Text( const wxPoint& aPos,
|
||||
enum EDA_COLOR_T aColor,
|
||||
const wxString& aText,
|
||||
int aOrient,
|
||||
const wxSize& aSize,
|
||||
enum EDA_TEXT_HJUSTIFY_T aH_justify,
|
||||
enum EDA_TEXT_VJUSTIFY_T aV_justify,
|
||||
int aWidth,
|
||||
bool aItalic,
|
||||
bool aBold )
|
||||
{
|
||||
// Emit native PDF text (if requested)
|
||||
if( psTextMode != PSTEXTMODE_STROKE )
|
||||
{
|
||||
const char *fontname = aItalic ? (aBold ? "/KicadFontBI" : "/KicadFontI")
|
||||
: (aBold ? "/KicadFontB" : "/KicadFont");
|
||||
|
||||
// Compute the copious tranformation parameters
|
||||
double ctm_a, ctm_b, ctm_c, ctm_d, ctm_e, ctm_f;
|
||||
double wideningFactor, heightFactor;
|
||||
computeTextParameters( aPos, aText, aOrient, aSize, aH_justify,
|
||||
aV_justify, aWidth, aItalic, aBold,
|
||||
&wideningFactor, &ctm_a, &ctm_b, &ctm_c,
|
||||
&ctm_d, &ctm_e, &ctm_f, &heightFactor );
|
||||
|
||||
SetColor( aColor );
|
||||
SetCurrentLineWidth( aWidth );
|
||||
|
||||
/* We use the full CTM instead of the text matrix because the same
|
||||
coordinate system will be used for the overlining. Also the %f
|
||||
for the trig part of the matrix to avoid %g going in exponential
|
||||
format (which is not supported)
|
||||
Rendermode 0 shows the text, rendermode 3 is invisible */
|
||||
fprintf( workFile, "q %f %f %f %f %g %g cm BT %s %g Tf %d Tr %g Tz ",
|
||||
ctm_a, ctm_b, ctm_c, ctm_d, ctm_e, ctm_f,
|
||||
fontname, heightFactor,
|
||||
(psTextMode == PSTEXTMODE_NATIVE) ? 0 : 3,
|
||||
wideningFactor * 100 );
|
||||
|
||||
// The text must be escaped correctly
|
||||
fputsPostscriptString( workFile, aText );
|
||||
fputs( " Tj ET\n", workFile );
|
||||
|
||||
/* We are still in text coordinates, plot the overbars (if we're
|
||||
* not doing phantom text) */
|
||||
if( psTextMode == PSTEXTMODE_NATIVE )
|
||||
{
|
||||
std::vector<int> pos_pairs;
|
||||
postscriptOverlinePositions( aText, aSize.x, aItalic, aBold, &pos_pairs );
|
||||
int overbar_y = KiROUND( aSize.y * 1.1 );
|
||||
for( unsigned i = 0; i < pos_pairs.size(); i += 2)
|
||||
{
|
||||
/* This is a nontrivial situation: we are *not* in the user
|
||||
coordinate system, so the userToDeviceCoordinates function
|
||||
can't be used! Strange as it may seem, the userToDeviceSize
|
||||
is the right function to use here... */
|
||||
DPOINT dev_from = userToDeviceSize( wxSize( pos_pairs[i], overbar_y ) );
|
||||
DPOINT dev_to = userToDeviceSize( wxSize( pos_pairs[i + 1], overbar_y ) );
|
||||
fprintf( workFile, "%g %g m %g %g l ",
|
||||
dev_from.x, dev_from.y, dev_to.x, dev_to.y );
|
||||
}
|
||||
}
|
||||
|
||||
// Stroke and restore the CTM
|
||||
fputs( "S Q\n", workFile );
|
||||
}
|
||||
|
||||
// Plot the stroked text (if requested)
|
||||
if( psTextMode != PSTEXTMODE_NATIVE )
|
||||
{
|
||||
PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify,
|
||||
aWidth, aItalic, aBold );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,309 @@
|
|||
/** @file dialog_plot_schematic_PDF.cpp
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2010 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr
|
||||
* Copyright (C) 1992-2010 KiCad Developers, see change_log.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 2
|
||||
* 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, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <gr_basic.h>
|
||||
#include <confirm.h>
|
||||
#include <worksheet.h>
|
||||
#include <plot_common.h>
|
||||
#include <class_sch_screen.h>
|
||||
#include <wxEeschemaStruct.h>
|
||||
#include <base_units.h>
|
||||
|
||||
#include <general.h>
|
||||
#include <protos.h>
|
||||
#include <sch_sheet_path.h>
|
||||
|
||||
|
||||
enum PageFormatReq {
|
||||
PAGE_SIZE_AUTO,
|
||||
PAGE_SIZE_A4,
|
||||
PAGE_SIZE_A
|
||||
};
|
||||
|
||||
#include <dialog_plot_schematic_PDF_base.h>
|
||||
|
||||
class DIALOG_PLOT_SCHEMATIC_PDF : public DIALOG_PLOT_SCHEMATIC_PDF_BASE
|
||||
{
|
||||
private:
|
||||
SCH_EDIT_FRAME* m_Parent;
|
||||
|
||||
public:
|
||||
|
||||
/// Constructors
|
||||
DIALOG_PLOT_SCHEMATIC_PDF( SCH_EDIT_FRAME* parent );
|
||||
|
||||
private:
|
||||
static bool m_plotColorOpt;
|
||||
static int m_pageSizeSelect;
|
||||
static bool m_plot_Sheet_Ref;
|
||||
bool m_select_PlotAll;
|
||||
private:
|
||||
void OnPlotCurrent( wxCommandEvent& event );
|
||||
void OnPlotAll( wxCommandEvent& event );
|
||||
void OnCancelClick( wxCommandEvent& event );
|
||||
|
||||
void initDlg();
|
||||
void initOptVars();
|
||||
void createPDFFile();
|
||||
void plotOneSheet( PDF_PLOTTER *plotter, SCH_SCREEN* screen );
|
||||
void plotSetupPage( PDF_PLOTTER *plotter, SCH_SCREEN* screen );
|
||||
};
|
||||
|
||||
// static members (static to remember last state):
|
||||
bool DIALOG_PLOT_SCHEMATIC_PDF::m_plotColorOpt = false;
|
||||
int DIALOG_PLOT_SCHEMATIC_PDF::m_pageSizeSelect = PAGE_SIZE_AUTO;
|
||||
bool DIALOG_PLOT_SCHEMATIC_PDF::m_plot_Sheet_Ref = true;
|
||||
|
||||
|
||||
void SCH_EDIT_FRAME::ToPlot_PDF( wxCommandEvent& event )
|
||||
{
|
||||
DIALOG_PLOT_SCHEMATIC_PDF dlg( this );
|
||||
|
||||
dlg.ShowModal();
|
||||
}
|
||||
|
||||
|
||||
DIALOG_PLOT_SCHEMATIC_PDF::DIALOG_PLOT_SCHEMATIC_PDF( SCH_EDIT_FRAME* parent ) :
|
||||
DIALOG_PLOT_SCHEMATIC_PDF_BASE( parent )
|
||||
{
|
||||
m_Parent = parent;
|
||||
m_select_PlotAll = false;
|
||||
initDlg();
|
||||
|
||||
GetSizer()->SetSizeHints( this );
|
||||
Centre();
|
||||
m_buttonPlotAll->SetDefault();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* Control creation for DIALOG_PLOT_SCHEMATIC_PDF
|
||||
*/
|
||||
|
||||
void DIALOG_PLOT_SCHEMATIC_PDF::initDlg()
|
||||
{
|
||||
SetFocus(); // make the ESC work
|
||||
|
||||
// Set options
|
||||
m_SizeOption->SetSelection( m_pageSizeSelect );
|
||||
m_PlotPDFColorOption->SetSelection( m_plotColorOpt ? 1 : 0 );
|
||||
m_Plot_Sheet_Ref_Ctrl->SetValue( m_plot_Sheet_Ref );
|
||||
|
||||
AddUnitSymbol( *m_defaultLineWidthTitle, g_UserUnit );
|
||||
PutValueInLocalUnits( *m_DefaultLineSizeCtrl, g_DrawDefaultLineThickness );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON
|
||||
*/
|
||||
|
||||
void DIALOG_PLOT_SCHEMATIC_PDF::OnPlotCurrent( wxCommandEvent& event )
|
||||
{
|
||||
m_select_PlotAll = false;
|
||||
|
||||
initOptVars();
|
||||
createPDFFile();
|
||||
m_MsgBox->AppendText( wxT( "*****\n" ) );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON1
|
||||
*/
|
||||
|
||||
void DIALOG_PLOT_SCHEMATIC_PDF::OnPlotAll( wxCommandEvent& event )
|
||||
{
|
||||
m_select_PlotAll = true;
|
||||
|
||||
initOptVars();
|
||||
createPDFFile();
|
||||
m_MsgBox->AppendText( wxT( "*****\n" ) );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL
|
||||
*/
|
||||
|
||||
void DIALOG_PLOT_SCHEMATIC_PDF::OnCancelClick( wxCommandEvent& event )
|
||||
{
|
||||
initOptVars();
|
||||
EndModal( 0 );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PLOT_SCHEMATIC_PDF::initOptVars()
|
||||
{
|
||||
m_plot_Sheet_Ref = m_Plot_Sheet_Ref_Ctrl->GetValue();
|
||||
m_plotColorOpt = m_PlotPDFColorOption->GetSelection();
|
||||
m_pageSizeSelect = m_SizeOption->GetSelection();
|
||||
g_DrawDefaultLineThickness = ReturnValueFromTextCtrl( *m_DefaultLineSizeCtrl );
|
||||
|
||||
if( g_DrawDefaultLineThickness < 1 )
|
||||
g_DrawDefaultLineThickness = 1;
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PLOT_SCHEMATIC_PDF::createPDFFile()
|
||||
{
|
||||
SCH_SCREEN* screen = m_Parent->GetScreen();
|
||||
SCH_SHEET_PATH* sheetpath;
|
||||
SCH_SHEET_PATH oldsheetpath = m_Parent->GetCurrentSheet(); // sheetpath is saved here
|
||||
wxPoint plot_offset;
|
||||
|
||||
/* When printing all pages, the printed page is not the current page. In
|
||||
* complex hierarchies, we must update component references and others
|
||||
* parameters in the given printed SCH_SCREEN, accordint to the sheet path
|
||||
* because in complex hierarchies a SCH_SCREEN (a drawing ) is shared
|
||||
* between many sheets and component references depend on the actual sheet
|
||||
* path used
|
||||
*/
|
||||
SCH_SHEET_LIST SheetList( NULL );
|
||||
|
||||
sheetpath = SheetList.GetFirst();
|
||||
|
||||
// Allocate the plotter and set the job level parameter
|
||||
PDF_PLOTTER* plotter = new PDF_PLOTTER();
|
||||
plotter->SetDefaultLineWidth( g_DrawDefaultLineThickness );
|
||||
plotter->SetColorMode( m_plotColorOpt );
|
||||
plotter->SetCreator( wxT( "Eeschema-PDF" ) );
|
||||
plotter->SetPsTextMode( PSTEXTMODE_PHANTOM );
|
||||
|
||||
|
||||
// First page handling is different
|
||||
bool first_page = true;
|
||||
|
||||
do
|
||||
{
|
||||
// Step over the schematic hierarchy
|
||||
if( m_select_PlotAll )
|
||||
{
|
||||
SCH_SHEET_PATH list;
|
||||
if( list.BuildSheetPathInfoFromSheetPathValue( sheetpath->Path() ) )
|
||||
{
|
||||
m_Parent->SetCurrentSheet( list );
|
||||
m_Parent->GetCurrentSheet().UpdateAllScreenReferences();
|
||||
m_Parent->SetSheetNumberAndCount();
|
||||
screen = m_Parent->GetCurrentSheet().LastScreen();
|
||||
}
|
||||
else // Should not happen
|
||||
wxASSERT( 0 );
|
||||
|
||||
sheetpath = SheetList.GetNext();
|
||||
}
|
||||
|
||||
if( first_page ) {
|
||||
wxString msg;
|
||||
wxString plotFileName = m_Parent->GetUniqueFilenameForCurrentSheet()
|
||||
+ wxT( ".pdf" );
|
||||
msg.Printf( _( "Plot: %s " ), GetChars( plotFileName ) );
|
||||
m_MsgBox->AppendText( msg );
|
||||
|
||||
FILE* output_file = wxFopen( plotFileName, wxT( "wb" ) );
|
||||
|
||||
if( output_file == NULL )
|
||||
{
|
||||
msg = wxT( "\n** " );
|
||||
msg += _( "Unable to create " ) + plotFileName + wxT( " **\n" );
|
||||
m_MsgBox->AppendText( msg );
|
||||
wxBell();
|
||||
return;
|
||||
}
|
||||
// Open the plotter and do the first page
|
||||
SetLocaleTo_C_standard();
|
||||
plotter->SetFilename( plotFileName );
|
||||
plotSetupPage( plotter, screen );
|
||||
plotter->StartPlot( output_file );
|
||||
first_page = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For the following pages you need to close the (finished) page,
|
||||
reconfigure, and then start a new one */
|
||||
plotter->ClosePage();
|
||||
plotSetupPage( plotter, screen );
|
||||
plotter->StartPage();
|
||||
}
|
||||
plotOneSheet( plotter, screen );
|
||||
} while (m_select_PlotAll && sheetpath );
|
||||
|
||||
// Everything done, close the plot and restore the environment
|
||||
plotter->EndPlot();
|
||||
delete plotter;
|
||||
SetLocaleTo_Default();
|
||||
|
||||
// Restore the previous sheet
|
||||
m_Parent->SetCurrentSheet( oldsheetpath );
|
||||
m_Parent->GetCurrentSheet().UpdateAllScreenReferences();
|
||||
m_Parent->SetSheetNumberAndCount();
|
||||
}
|
||||
|
||||
void DIALOG_PLOT_SCHEMATIC_PDF::plotSetupPage( PDF_PLOTTER* plotter,
|
||||
SCH_SCREEN* screen)
|
||||
{
|
||||
PAGE_INFO plotPage; // page size selected to plot
|
||||
// Considerations on page size and scaling requests
|
||||
PAGE_INFO actualPage = screen->GetPageSettings(); // page size selected in schematic
|
||||
switch( m_pageSizeSelect )
|
||||
{
|
||||
case PAGE_SIZE_A:
|
||||
plotPage.SetType( wxT( "A" ) );
|
||||
plotPage.SetPortrait( actualPage.IsPortrait() );
|
||||
break;
|
||||
|
||||
case PAGE_SIZE_A4:
|
||||
plotPage.SetType( wxT( "A4" ) );
|
||||
plotPage.SetPortrait( actualPage.IsPortrait() );
|
||||
break;
|
||||
|
||||
case PAGE_SIZE_AUTO:
|
||||
default:
|
||||
plotPage = actualPage;
|
||||
break;
|
||||
}
|
||||
|
||||
double scalex = (double) plotPage.GetWidthMils() / actualPage.GetWidthMils();
|
||||
double scaley = (double) plotPage.GetHeightMils() / actualPage.GetHeightMils();
|
||||
double scale = MIN( scalex, scaley );
|
||||
plotter->SetViewport( wxPoint( 0, 0 ), IU_PER_DECIMILS, scale, 0 );
|
||||
plotter->SetPageSettings( plotPage );
|
||||
}
|
||||
|
||||
void DIALOG_PLOT_SCHEMATIC_PDF::plotOneSheet( PDF_PLOTTER* plotter,
|
||||
SCH_SCREEN* screen )
|
||||
{
|
||||
if( m_plot_Sheet_Ref )
|
||||
{
|
||||
plotter->SetColor( BLACK );
|
||||
m_Parent->PlotWorkSheet( plotter, screen );
|
||||
}
|
||||
|
||||
screen->Plot( plotter );
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Nov 17 2010)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "dialog_plot_schematic_PDF_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DIALOG_PLOT_SCHEMATIC_PDF_BASE::DIALOG_PLOT_SCHEMATIC_PDF_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
|
||||
{
|
||||
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
|
||||
|
||||
wxBoxSizer* bmainSizer;
|
||||
bmainSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bupperSizer;
|
||||
bupperSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxString m_SizeOptionChoices[] = { _("Schematic size"), _("Force size A4"), _("Force size A") };
|
||||
int m_SizeOptionNChoices = sizeof( m_SizeOptionChoices ) / sizeof( wxString );
|
||||
m_SizeOption = new wxRadioBox( this, wxID_ANY, _("Plot Page Size:"), wxDefaultPosition, wxDefaultSize, m_SizeOptionNChoices, m_SizeOptionChoices, 1, wxRA_SPECIFY_COLS );
|
||||
m_SizeOption->SetSelection( 0 );
|
||||
bupperSizer->Add( m_SizeOption, 1, wxALL, 5 );
|
||||
|
||||
|
||||
bupperSizer->Add( 10, 10, 0, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* sbSizerMiddle;
|
||||
sbSizerMiddle = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxString m_PlotPDFColorOptionChoices[] = { _("B/W"), _("Color") };
|
||||
int m_PlotPDFColorOptionNChoices = sizeof( m_PlotPDFColorOptionChoices ) / sizeof( wxString );
|
||||
m_PlotPDFColorOption = new wxRadioBox( this, wxID_ANY, _("Plot Mode:"), wxDefaultPosition, wxDefaultSize, m_PlotPDFColorOptionNChoices, m_PlotPDFColorOptionChoices, 1, wxRA_SPECIFY_COLS );
|
||||
m_PlotPDFColorOption->SetSelection( 0 );
|
||||
sbSizerMiddle->Add( m_PlotPDFColorOption, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_Plot_Sheet_Ref_Ctrl = new wxCheckBox( this, wxID_ANY, _("Print page references"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_Plot_Sheet_Ref_Ctrl->SetValue(true);
|
||||
sbSizerMiddle->Add( m_Plot_Sheet_Ref_Ctrl, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
bupperSizer->Add( sbSizerMiddle, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bupperSizer->Add( 10, 10, 0, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bbuttonsSizer;
|
||||
bbuttonsSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_buttonPlotPage = new wxButton( this, wxID_ANY, _("&Plot Page"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bbuttonsSizer->Add( m_buttonPlotPage, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_buttonPlotAll = new wxButton( this, wxID_ANY, _("Plot A&LL"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bbuttonsSizer->Add( m_buttonPlotAll, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_buttonClose = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bbuttonsSizer->Add( m_buttonClose, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
bupperSizer->Add( bbuttonsSizer, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
bmainSizer->Add( bupperSizer, 0, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizerLineWidth;
|
||||
bSizerLineWidth = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_defaultLineWidthTitle = new wxStaticText( this, wxID_ANY, _("Default line width:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_defaultLineWidthTitle->Wrap( -1 );
|
||||
bSizerLineWidth->Add( m_defaultLineWidthTitle, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_DefaultLineSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerLineWidth->Add( m_DefaultLineSizeCtrl, 1, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
bmainSizer->Add( bSizerLineWidth, 0, wxEXPAND, 5 );
|
||||
|
||||
m_staticText1 = new wxStaticText( this, wxID_ANY, _("Messages :"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText1->Wrap( -1 );
|
||||
bmainSizer->Add( m_staticText1, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_MsgBox = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY );
|
||||
m_MsgBox->SetMinSize( wxSize( -1,150 ) );
|
||||
|
||||
bmainSizer->Add( m_MsgBox, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
this->SetSizer( bmainSizer );
|
||||
this->Layout();
|
||||
|
||||
this->Centre( wxBOTH );
|
||||
|
||||
// Connect Events
|
||||
m_buttonPlotPage->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_PDF_BASE::OnPlotCurrent ), NULL, this );
|
||||
m_buttonPlotAll->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_PDF_BASE::OnPlotAll ), NULL, this );
|
||||
m_buttonClose->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_PDF_BASE::OnCancelClick ), NULL, this );
|
||||
}
|
||||
|
||||
DIALOG_PLOT_SCHEMATIC_PDF_BASE::~DIALOG_PLOT_SCHEMATIC_PDF_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_buttonPlotPage->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_PDF_BASE::OnPlotCurrent ), NULL, this );
|
||||
m_buttonPlotAll->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_PDF_BASE::OnPlotAll ), NULL, this );
|
||||
m_buttonClose->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_PDF_BASE::OnCancelClick ), NULL, this );
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,63 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Nov 17 2010)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __dialog_plot_schematic_PDF_base__
|
||||
#define __dialog_plot_schematic_PDF_base__
|
||||
|
||||
#include <wx/intl.h>
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <wx/radiobox.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class DIALOG_PLOT_SCHEMATIC_PDF_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class DIALOG_PLOT_SCHEMATIC_PDF_BASE : public wxDialog
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxRadioBox* m_SizeOption;
|
||||
|
||||
wxRadioBox* m_PlotPDFColorOption;
|
||||
wxCheckBox* m_Plot_Sheet_Ref_Ctrl;
|
||||
|
||||
wxButton* m_buttonPlotPage;
|
||||
wxButton* m_buttonPlotAll;
|
||||
wxButton* m_buttonClose;
|
||||
wxStaticText* m_defaultLineWidthTitle;
|
||||
wxTextCtrl* m_DefaultLineSizeCtrl;
|
||||
wxStaticText* m_staticText1;
|
||||
wxTextCtrl* m_MsgBox;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void OnPlotCurrent( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnPlotAll( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
DIALOG_PLOT_SCHEMATIC_PDF_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Plot PDF"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 387,365 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
~DIALOG_PLOT_SCHEMATIC_PDF_BASE();
|
||||
|
||||
};
|
||||
|
||||
#endif //__dialog_plot_schematic_PDF_base__
|
Loading…
Reference in New Issue