7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-20 15:01:41 +00:00

Move SVG_PLOTTER to {fmt} to punt locale issues

This commit is contained in:
Marek Roszko 2025-03-05 18:42:05 -05:00
parent ff6eb9c091
commit 237953fd55
6 changed files with 268 additions and 254 deletions

View File

@ -92,6 +92,7 @@
#include <font/font.h>
#include <macros.h>
#include <trigo.h>
#include <fmt/format.h>
#include <cstdint>
#include <wx/mstream.h>
@ -230,14 +231,14 @@ void SVG_PLOTTER::setSVGPlotStyle( int aLineWidth, bool aIsGroup, const std::str
else
{
// output the background fill color
fprintf( m_outputFile, "fill:#%6.6lX; ", m_brush_rgb_color );
fmt::print( m_outputFile, "fill:#{:06X}; ", m_brush_rgb_color );
switch( m_fillMode )
{
case FILL_T::FILLED_SHAPE:
case FILL_T::FILLED_WITH_BG_BODYCOLOR:
case FILL_T::FILLED_WITH_COLOR:
fprintf( m_outputFile, "fill-opacity:%.*f; ", m_precision, m_brush_alpha );
fmt::print( m_outputFile, "fill-opacity:{:.{}f}; ", m_brush_alpha, m_precision );
break;
default: break;
}
@ -256,34 +257,36 @@ void SVG_PLOTTER::setSVGPlotStyle( int aLineWidth, bool aIsGroup, const std::str
// So we use only 4 digits in mantissa for stroke-width.
// TODO: perhaps used only 3 or 4 digits in mantissa for all values in mm, because some
// issues were previously reported reported when using nm as integer units
fprintf( m_outputFile, "\nstroke:#%6.6lX; stroke-width:%.*f; stroke-opacity:1; \n",
m_pen_rgb_color, m_precision, pen_w );
fmt::print( m_outputFile, "\nstroke:#{:06X}; stroke-width:{:.{}f}; stroke-opacity:1; \n",
m_pen_rgb_color, pen_w, m_precision );
fputs( "stroke-linecap:round; stroke-linejoin:round;", m_outputFile );
//set any extra attributes for non-solid lines
switch( m_dashed )
{
case LINE_STYLE::DASH:
fprintf( m_outputFile, "stroke-dasharray:%.*f,%.*f;", m_precision,
GetDashMarkLenIU( aLineWidth ), m_precision, GetDashGapLenIU( aLineWidth ) );
fmt::print( m_outputFile, "stroke-dasharray:{:.{}f},{:.{}f};",
GetDashMarkLenIU( aLineWidth ), m_precision,
GetDashGapLenIU( aLineWidth ), m_precision );
break;
case LINE_STYLE::DOT:
fprintf( m_outputFile, "stroke-dasharray:%f,%f;", GetDotMarkLenIU( aLineWidth ),
GetDashGapLenIU( aLineWidth ) );
fmt::print( m_outputFile, "stroke-dasharray:{:f},{:f};", GetDotMarkLenIU( aLineWidth ),
GetDashGapLenIU( aLineWidth ) );
break;
case LINE_STYLE::DASHDOT:
fprintf( m_outputFile, "stroke-dasharray:%f,%f,%f,%f;", GetDashMarkLenIU( aLineWidth ),
GetDashGapLenIU( aLineWidth ), GetDotMarkLenIU( aLineWidth ),
GetDashGapLenIU( aLineWidth ) );
fmt::print( m_outputFile, "stroke-dasharray:{:f},{:f},{:f},{:f};",
GetDashMarkLenIU( aLineWidth ),
GetDashGapLenIU( aLineWidth ), GetDotMarkLenIU( aLineWidth ),
GetDashGapLenIU( aLineWidth ) );
break;
case LINE_STYLE::DASHDOTDOT:
fprintf( m_outputFile, "stroke-dasharray:%f,%f,%f,%f,%f,%f;",
GetDashMarkLenIU( aLineWidth ), GetDashGapLenIU( aLineWidth ),
GetDotMarkLenIU( aLineWidth ), GetDashGapLenIU( aLineWidth ),
GetDotMarkLenIU( aLineWidth ), GetDashGapLenIU( aLineWidth ) );
fmt::print( m_outputFile, "stroke-dasharray:{:f},{:f},{:f},{:f},{:f},{:f};",
GetDashMarkLenIU( aLineWidth ), GetDashGapLenIU( aLineWidth ),
GetDotMarkLenIU( aLineWidth ), GetDashGapLenIU( aLineWidth ),
GetDotMarkLenIU( aLineWidth ), GetDashGapLenIU( aLineWidth ) );
break;
case LINE_STYLE::DEFAULT:
@ -342,10 +345,10 @@ void SVG_PLOTTER::EndBlock( void* aData )
void SVG_PLOTTER::emitSetRGBColor( double r, double g, double b, double a )
{
int red = (int) ( 255.0 * r );
int green = (int) ( 255.0 * g );
int blue = (int) ( 255.0 * b );
long rgb_color = ( red << 16 ) | ( green << 8 ) | blue;
uint32_t red = (uint32_t) ( 255.0 * r );
uint32_t green = (uint32_t) ( 255.0 * g );
uint32_t blue = (uint32_t) ( 255.0 * b );
uint32_t rgb_color = ( red << 16 ) | ( green << 8 ) | blue;
if( m_pen_rgb_color != rgb_color || m_brush_alpha != a )
{
@ -394,22 +397,22 @@ void SVG_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int
// so use a line when happens.
if( rect_dev.GetSize().x == 0.0 || rect_dev.GetSize().y == 0.0 ) // Draw a line
{
fprintf( m_outputFile,
"<line x1=\"%.*f\" y1=\"%.*f\" x2=\"%.*f\" y2=\"%.*f\" />\n",
m_precision, rect_dev.GetPosition().x,
m_precision, rect_dev.GetPosition().y,
m_precision, rect_dev.GetEnd().x,
m_precision, rect_dev.GetEnd().y );
fmt::print( m_outputFile,
"<line x1=\"{:.{}f}\" y1=\"{:.{}f}\" x2=\"{:.{}f}\" y2=\"{:.{}f}\" />\n",
rect_dev.GetPosition().x, m_precision,
rect_dev.GetPosition().y, m_precision,
rect_dev.GetEnd().x, m_precision,
rect_dev.GetEnd().y, m_precision );
}
else
{
fprintf( m_outputFile,
"<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" rx=\"%f\" />\n",
rect_dev.GetPosition().x,
rect_dev.GetPosition().y,
rect_dev.GetSize().x,
rect_dev.GetSize().y,
0.0 /* radius of rounded corners */ );
fmt::print( m_outputFile,
"<rect x=\"{:f}\" y=\"{:f}\" width=\"{:f}\" height=\"{:f}\" rx=\"{:f}\" />\n",
rect_dev.GetPosition().x,
rect_dev.GetPosition().y,
rect_dev.GetSize().x,
rect_dev.GetSize().y,
0.0 /* radius of rounded corners */ );
}
}
@ -434,11 +437,11 @@ void SVG_PLOTTER::Circle( const VECTOR2I& pos, int diametre, FILL_T fill, int wi
radius = userToDeviceSize( ( diametre / 2.0 ) + ( width / 2.0 ) );
}
fprintf( m_outputFile,
"<circle cx=\"%.*f\" cy=\"%.*f\" r=\"%.*f\" /> \n",
m_precision, pos_dev.x,
m_precision, pos_dev.y,
m_precision, radius );
fmt::print( m_outputFile,
"<circle cx=\"{:.{}f}\" cy=\"{:.{}f}\" r=\"{:.{}f}\" /> \n",
pos_dev.x, m_precision,
pos_dev.y, m_precision,
radius, m_precision );
}
@ -526,18 +529,18 @@ void SVG_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
if( m_graphics_changed )
setSVGPlotStyle( GetCurrentLineWidth() );
fprintf( m_outputFile,
"<path d=\"M%.*f %.*f A%.*f %.*f 0.0 %d %d %.*f %.*f L %.*f %.*f Z\" />\n",
m_precision, start.x,
m_precision, start.y,
m_precision, radius_device,
m_precision, radius_device,
flg_arc,
flg_sweep,
m_precision, end.x,
m_precision, end.y,
m_precision, centre_device.x,
m_precision, centre_device.y );
fmt::print( m_outputFile,
"<path d=\"M{:.{}f} {:.{}f} A{:.{}f} {:.{}f} 0.0 {:d} {:d} {:.{}f} {:.{}f} L {:.{}f} {:.{}f} Z\" />\n",
start.x, m_precision,
start.y, m_precision,
radius_device, m_precision,
radius_device, m_precision,
flg_arc,
flg_sweep,
end.x, m_precision,
end.y, m_precision,
centre_device.x, m_precision,
centre_device.y, m_precision );
}
setFillMode( FILL_T::NO_FILL );
@ -546,16 +549,16 @@ void SVG_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
if( m_graphics_changed )
setSVGPlotStyle( GetCurrentLineWidth() );
fprintf( m_outputFile,
"<path d=\"M%.*f %.*f A%.*f %.*f 0.0 %d %d %.*f %.*f\" />\n",
m_precision, start.x,
m_precision, start.y,
m_precision, radius_device,
m_precision, radius_device,
flg_arc,
flg_sweep,
m_precision, end.x,
m_precision, end.y );
fmt::print( m_outputFile,
"<path d=\"M{:.{}f} {:.{}f} A{:.{}f} {:.{}f} 0.0 {:d} {:d} {:.{}f} {:.{}f}\" />\n",
start.x, m_precision,
start.y, m_precision,
radius_device, m_precision,
radius_device, m_precision,
flg_arc,
flg_sweep,
end.x, m_precision,
end.y, m_precision );
}
@ -576,16 +579,16 @@ void SVG_PLOTTER::BezierCurve( const VECTOR2I& aStart, const VECTOR2I& aControl1
VECTOR2D end = userToDeviceCoordinates( aEnd );
// Generate a cubic curve: start point and 3 other control points.
fprintf( m_outputFile,
"<path d=\"M%.*f,%.*f C%.*f,%.*f %.*f,%.*f %.*f,%.*f\" />\n",
m_precision, start.x,
m_precision, start.y,
m_precision, ctrl1.x,
m_precision, ctrl1.y,
m_precision, ctrl2.x,
m_precision, ctrl2.y,
m_precision, end.x,
m_precision, end.y );
fmt::print( m_outputFile,
"<path d=\"M{:.{}f},{:.{}f} C{:.{}f},{:.{}f} {:.{}f},{:.{}f} {:.{}f},{:.{}f}\" />\n",
start.x, m_precision,
start.y, m_precision,
ctrl1.x,m_precision,
ctrl1.y, m_precision,
ctrl2.x, m_precision,
ctrl2.y, m_precision,
end.x, m_precision,
end.y, m_precision );
#else
PLOTTER::BezierCurve( aStart, aControl1, aControl2, aEnd, aTolerance, aLineThickness );
#endif
@ -600,7 +603,7 @@ void SVG_PLOTTER::PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFi
setFillMode( aFill );
SetCurrentLineWidth( aWidth );
fprintf( m_outputFile, "<path ");
fputs( "<path ", m_outputFile );
switch( aFill )
{
@ -619,32 +622,26 @@ void SVG_PLOTTER::PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFi
}
VECTOR2D pos = userToDeviceCoordinates( aCornerList[0] );
fprintf( m_outputFile,
"d=\"M %.*f,%.*f\n",
m_precision, pos.x,
m_precision, pos.y );
fmt::print( m_outputFile, "d=\"M {:.{}f},{:.{}f}\n", pos.x, m_precision, pos.y, m_precision );
for( unsigned ii = 1; ii < aCornerList.size() - 1; ii++ )
{
pos = userToDeviceCoordinates( aCornerList[ii] );
fprintf( m_outputFile,
"%.*f,%.*f\n",
m_precision, pos.x,
m_precision, pos.y );
fmt::print( m_outputFile, "{:.{}f},{:.{}f}\n", pos.x, m_precision, pos.y, m_precision );
}
// If the corner list ends where it begins, then close the poly
if( aCornerList.front() == aCornerList.back() )
{
fprintf( m_outputFile, "Z\" /> \n" );
fputs( "Z\" /> \n", m_outputFile );
}
else
{
pos = userToDeviceCoordinates( aCornerList.back() );
fprintf( m_outputFile,
"%.*f,%.*f\n\" /> \n",
m_precision, pos.x,
m_precision, pos.y );
fmt::print( m_outputFile,
"{:.{}f},{:.{}f}\n\" /> \n",
pos.x, m_precision,
pos.y, m_precision );
}
}
@ -686,25 +683,23 @@ void SVG_PLOTTER::PlotImage( const wxImage& aImage, const VECTOR2I& aPos, double
img_stream.CopyTo( buffer.data(), buffer.size() );
base64::encode( buffer, encoded );
fprintf( m_outputFile,
"<image x=\"%f\" y=\"%f\" xlink:href=\"data:image/png;base64,",
userToDeviceSize( start.x ),
userToDeviceSize( start.y ) );
fmt::print( m_outputFile,
"<image x=\"{:f}\" y=\"{:f}\" xlink:href=\"data:image/png;base64,",
userToDeviceSize( start.x ),
userToDeviceSize( start.y ) );
for( size_t i = 0; i < encoded.size(); i++ )
{
fprintf( m_outputFile, "%c", static_cast<char>( encoded[i] ) );
fmt::print( m_outputFile, "{}", static_cast<char>( encoded[i] ) );
if( ( i % 64 ) == 63 )
fprintf( m_outputFile, "\n" );
fputs( "\n", m_outputFile );
}
fprintf( m_outputFile,
"\"\npreserveAspectRatio=\"none\" width=\"%.*f\" height=\"%.*f\" />",
m_precision,
userToDeviceSize( drawsize.x ),
m_precision,
userToDeviceSize( drawsize.y ) );
fmt::print( m_outputFile,
"\"\npreserveAspectRatio=\"none\" width=\"{:.{}f}\" height=\"{:.{}f}\" />",
userToDeviceSize( drawsize.x ), m_precision,
userToDeviceSize( drawsize.y ), m_precision );
}
}
@ -736,9 +731,9 @@ void SVG_PLOTTER::PenTo( const VECTOR2I& pos, char plume )
if( m_graphics_changed )
setSVGPlotStyle( GetCurrentLineWidth() );
fprintf( m_outputFile, "<path d=\"M%.*f %.*f\n",
m_precision, pos_dev.x,
m_precision, pos_dev.y );
fmt::print( m_outputFile, "<path d=\"M{:.{}f} {:.{}f}\n",
pos_dev.x, m_precision,
pos_dev.y, m_precision );
}
else if( m_penState != plume || pos != m_penLastpos )
{
@ -747,9 +742,9 @@ void SVG_PLOTTER::PenTo( const VECTOR2I& pos, char plume )
VECTOR2D pos_dev = userToDeviceCoordinates( pos );
fprintf( m_outputFile, "L%.*f %.*f\n",
m_precision, pos_dev.x,
m_precision, pos_dev.y );
fmt::print( m_outputFile, "L{:.{}f} {:.{}f}\n",
pos_dev.x, m_precision,
pos_dev.y, m_precision );
}
m_penState = plume;
@ -782,39 +777,36 @@ bool SVG_PLOTTER::StartPlot( const wxString& aPageNumber )
// Write viewport pos and size
VECTOR2D origin; // TODO set to actual value
fprintf( m_outputFile,
" width=\"%.*fmm\" height=\"%.*fmm\" viewBox=\"%.*f %.*f %.*f %.*f\">\n",
m_precision, (double) m_paperSize.x / m_IUsPerDecimil * 2.54 / 1000,
m_precision, (double) m_paperSize.y / m_IUsPerDecimil * 2.54 / 1000,
m_precision, origin.x, m_precision, origin.y,
m_precision, m_paperSize.x * m_iuPerDeviceUnit,
m_precision, m_paperSize.y * m_iuPerDeviceUnit);
fmt::print( m_outputFile,
" width=\"{:.{}f}mm\" height=\"{:.{}f}mm\" viewBox=\"{:.{}f} {:.{}f} {:.{}f} {:.{}f}\">\n",
(double) m_paperSize.x / m_IUsPerDecimil * 2.54 / 1000, m_precision,
(double) m_paperSize.y / m_IUsPerDecimil * 2.54 / 1000, m_precision,
origin.x, m_precision, origin.y, m_precision,
m_paperSize.x * m_iuPerDeviceUnit, m_precision,
m_paperSize.y * m_iuPerDeviceUnit, m_precision );
// Write title
char date_buf[250];
time_t ltime = time( nullptr );
strftime( date_buf, 250, "%Y/%m/%d %H:%M:%S", localtime( &ltime ) );
wxString date = GetISO8601CurrentDateTime();
fprintf( m_outputFile,
"<title>SVG Image created as %s date %s </title>\n",
TO_UTF8( XmlEsc( wxFileName( m_filename ).GetFullName() ) ),
date_buf );
fmt::print( m_outputFile,
"<title>SVG Image created as {} date {} </title>\n",
TO_UTF8( XmlEsc( wxFileName( m_filename ).GetFullName() ) ),
TO_UTF8( date ) );
// End of header
fprintf( m_outputFile,
" <desc>Image generated by %s </desc>\n",
TO_UTF8( XmlEsc( m_creator ) ) );
fmt::print( m_outputFile, " <desc>Image generated by {} </desc>\n",
TO_UTF8( XmlEsc( m_creator ) ) );
// output the pen and brush color (RVB values in hex) and opacity
double opacity = 1.0; // 0.0 (transparent to 1.0 (solid)
fprintf( m_outputFile,
"<g style=\"fill:#%6.6lX; fill-opacity:%.*f;stroke:#%6.6lX; stroke-opacity:%.*f;\n",
m_brush_rgb_color,
m_precision,
m_brush_alpha,
m_pen_rgb_color,
m_precision,
opacity );
fmt::print( m_outputFile,
"<g style=\"fill:#{:06X}; fill-opacity:{:.{}f};stroke:#{:06X}; stroke-opacity:{:.{}f};\n",
m_brush_rgb_color,
m_brush_alpha,
m_precision,
m_pen_rgb_color,
opacity,
m_precision );
// output the pen cap and line joint
fputs( "stroke-linecap:round; stroke-linejoin:round;\"\n", m_outputFile );
@ -895,37 +887,36 @@ void SVG_PLOTTER::Text( const VECTOR2I& aPos,
{
if( !aOrient.IsZero() )
{
fprintf( m_outputFile,
"<g transform=\"rotate(%f %.*f %.*f)\">\n",
m_plotMirror ? aOrient.AsDegrees() : -aOrient.AsDegrees(),
m_precision,
anchor_pos_dev.x,
m_precision,
anchor_pos_dev.y );
fmt::print( m_outputFile,
"<g transform=\"rotate({:f} {:.{}f} {:.{}f})\">\n",
m_plotMirror ? aOrient.AsDegrees() : -aOrient.AsDegrees(),
anchor_pos_dev.x,
m_precision,
anchor_pos_dev.y,
m_precision );
}
fprintf( m_outputFile,
"<text x=\"%.*f\" y=\"%.*f\"\n",
m_precision,
text_pos_dev.x, m_precision,
text_pos_dev.y );
fmt::print( m_outputFile,
"<text x=\"{:.{}f}\" y=\"{:.{}f}\"\n",
text_pos_dev.x, m_precision,
text_pos_dev.y, m_precision );
/// If the text is mirrored, we should also mirror the hidden text to match
if( m_plotMirror != ( aSize.x < 0 ) )
{
fprintf( m_outputFile, "transform=\"scale(-1 1) translate(%f 0)\"\n",
-2 * text_pos_dev.x );
fmt::print( m_outputFile, "transform=\"scale(-1 1) translate({:f} 0)\"\n",
-2 * text_pos_dev.x );
}
fprintf( m_outputFile,
"textLength=\"%.*f\" font-size=\"%.*f\" lengthAdjust=\"spacingAndGlyphs\"\n"
"text-anchor=\"%s\" opacity=\"0\" stroke-opacity=\"0\">%s</text>\n",
m_precision,
sz_dev.x,
m_precision,
sz_dev.y,
hjust,
TO_UTF8( XmlEsc( aText ) ) );
fmt::print( m_outputFile,
"textLength=\"{:.{}f}\" font-size=\"{:.{}f}\" lengthAdjust=\"spacingAndGlyphs\"\n"
"text-anchor=\"{}\" opacity=\"0\" stroke-opacity=\"0\">{}</text>\n",
sz_dev.x,
m_precision,
sz_dev.y,
m_precision,
hjust,
TO_UTF8( XmlEsc( aText ) ) );
if( !aOrient.IsZero() )
fputs( "</g>\n", m_outputFile );
@ -934,9 +925,9 @@ void SVG_PLOTTER::Text( const VECTOR2I& aPos,
// Output the text again as graphics with a <desc> tag (for non-WYSIWYG search and for
// screen readers)
{
fprintf( m_outputFile,
"<g class=\"stroked-text\"><desc>%s</desc>\n",
TO_UTF8( XmlEsc( aText ) ) );
fmt::print( m_outputFile,
"<g class=\"stroked-text\"><desc>{}</desc>\n",
TO_UTF8( XmlEsc( aText ) ) );
PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, aWidth,
aItalic, aBold, aMultilineAllowed, aFont, aFontMetrics );

View File

@ -85,100 +85,105 @@ void PlotDrawingSheet( PLOTTER* plotter, const PROJECT* aProject, const TITLE_BL
drawList.BuildDrawItemsList( aPageInfo, aTitleBlock );
// Draw bitmaps first
for( DS_DRAW_ITEM_BASE* item = drawList.GetFirst(); item; item = drawList.GetNext() )
try
{
if( item->Type() == WSG_BITMAP_T )
// Draw bitmaps first
for( DS_DRAW_ITEM_BASE* item = drawList.GetFirst(); item; item = drawList.GetNext() )
{
DS_DRAW_ITEM_BITMAP* drawItem = (DS_DRAW_ITEM_BITMAP*) item;
DS_DATA_ITEM_BITMAP* bitmap = (DS_DATA_ITEM_BITMAP*) drawItem->GetPeer();
if( item->Type() == WSG_BITMAP_T )
{
DS_DRAW_ITEM_BITMAP* drawItem = (DS_DRAW_ITEM_BITMAP*) item;
DS_DATA_ITEM_BITMAP* bitmap = (DS_DATA_ITEM_BITMAP*) drawItem->GetPeer();
if( bitmap->m_ImageBitmap == nullptr )
if( bitmap->m_ImageBitmap == nullptr )
continue;
bitmap->m_ImageBitmap->PlotImage( plotter, drawItem->GetPosition(), plotColor,
PLOTTER::USE_DEFAULT_LINE_WIDTH );
}
}
// Draw other items
for( DS_DRAW_ITEM_BASE* item = drawList.GetFirst(); item; item = drawList.GetNext() )
{
if( item->Type() == WSG_BITMAP_T )
continue;
bitmap->m_ImageBitmap->PlotImage( plotter, drawItem->GetPosition(), plotColor,
PLOTTER::USE_DEFAULT_LINE_WIDTH );
plotter->SetColor( plotColor );
plotter->SetCurrentLineWidth( PLOTTER::USE_DEFAULT_LINE_WIDTH );
switch( item->Type() )
{
case WSG_LINE_T:
{
DS_DRAW_ITEM_LINE* line = (DS_DRAW_ITEM_LINE*) item;
plotter->SetCurrentLineWidth( std::max( line->GetPenWidth(), defaultPenWidth ) );
plotter->MoveTo( line->GetStart() );
plotter->FinishTo( line->GetEnd() );
}
break;
case WSG_RECT_T:
{
DS_DRAW_ITEM_RECT* rect = (DS_DRAW_ITEM_RECT*) item;
plotter->SetCurrentLineWidth( std::max( rect->GetPenWidth(), defaultPenWidth ) );
plotter->MoveTo( rect->GetStart() );
plotter->LineTo( VECTOR2I( rect->GetEnd().x, rect->GetStart().y ) );
plotter->LineTo( VECTOR2I( rect->GetEnd().x, rect->GetEnd().y ) );
plotter->LineTo( VECTOR2I( rect->GetStart().x, rect->GetEnd().y ) );
plotter->FinishTo( rect->GetStart() );
}
break;
case WSG_TEXT_T:
{
DS_DRAW_ITEM_TEXT* text = (DS_DRAW_ITEM_TEXT*) item;
KIFONT::FONT* font = text->GetFont();
COLOR4D color = plotColor;
if( !font )
{
font = KIFONT::FONT::GetFont( settings->GetDefaultFont(), text->IsBold(),
text->IsItalic() );
}
if( plotter->GetColorMode() && text->GetTextColor() != COLOR4D::UNSPECIFIED )
color = text->GetTextColor();
int penWidth = std::max( text->GetEffectiveTextPenWidth(), defaultPenWidth );
plotter->Text( text->GetTextPos(), color, text->GetShownText( true ),
text->GetTextAngle(), text->GetTextSize(), text->GetHorizJustify(),
text->GetVertJustify(), penWidth, text->IsItalic(), text->IsBold(),
text->IsMultilineAllowed(), font, text->GetFontMetrics() );
}
break;
case WSG_POLY_T:
{
DS_DRAW_ITEM_POLYPOLYGONS* poly = (DS_DRAW_ITEM_POLYPOLYGONS*) item;
int penWidth = poly->GetPenWidth();
std::vector<VECTOR2I> points;
for( int idx = 0; idx < poly->GetPolygons().OutlineCount(); ++idx )
{
points.clear();
SHAPE_LINE_CHAIN& outline = poly->GetPolygons().Outline( idx );
for( int ii = 0; ii < outline.PointCount(); ii++ )
points.emplace_back( outline.CPoint( ii ).x, outline.CPoint( ii ).y );
plotter->PlotPoly( points, FILL_T::FILLED_SHAPE, penWidth );
}
}
break;
default: wxFAIL_MSG( wxT( "PlotDrawingSheet(): Unknown drawing sheet item." ) ); break;
}
}
}
// Draw other items
for( DS_DRAW_ITEM_BASE* item = drawList.GetFirst(); item; item = drawList.GetNext() )
catch( ... )
{
if( item->Type() == WSG_BITMAP_T )
continue;
plotter->SetColor( plotColor );
plotter->SetCurrentLineWidth( PLOTTER::USE_DEFAULT_LINE_WIDTH );
switch( item->Type() )
{
case WSG_LINE_T:
{
DS_DRAW_ITEM_LINE* line = (DS_DRAW_ITEM_LINE*) item;
plotter->SetCurrentLineWidth( std::max( line->GetPenWidth(), defaultPenWidth ) );
plotter->MoveTo( line->GetStart() );
plotter->FinishTo( line->GetEnd() );
}
break;
case WSG_RECT_T:
{
DS_DRAW_ITEM_RECT* rect = (DS_DRAW_ITEM_RECT*) item;
plotter->SetCurrentLineWidth( std::max( rect->GetPenWidth(), defaultPenWidth ) );
plotter->MoveTo( rect->GetStart() );
plotter->LineTo( VECTOR2I( rect->GetEnd().x, rect->GetStart().y ) );
plotter->LineTo( VECTOR2I( rect->GetEnd().x, rect->GetEnd().y ) );
plotter->LineTo( VECTOR2I( rect->GetStart().x, rect->GetEnd().y ) );
plotter->FinishTo( rect->GetStart() );
}
break;
case WSG_TEXT_T:
{
DS_DRAW_ITEM_TEXT* text = (DS_DRAW_ITEM_TEXT*) item;
KIFONT::FONT* font = text->GetFont();
COLOR4D color = plotColor;
if( !font )
{
font = KIFONT::FONT::GetFont( settings->GetDefaultFont(), text->IsBold(),
text->IsItalic() );
}
if( plotter->GetColorMode() && text->GetTextColor() != COLOR4D::UNSPECIFIED )
color = text->GetTextColor();
int penWidth = std::max( text->GetEffectiveTextPenWidth(), defaultPenWidth );
plotter->Text( text->GetTextPos(), color, text->GetShownText( true ),
text->GetTextAngle(), text->GetTextSize(), text->GetHorizJustify(),
text->GetVertJustify(), penWidth, text->IsItalic(), text->IsBold(),
text->IsMultilineAllowed(), font, text->GetFontMetrics() );
}
break;
case WSG_POLY_T:
{
DS_DRAW_ITEM_POLYPOLYGONS* poly = (DS_DRAW_ITEM_POLYPOLYGONS*) item;
int penWidth = poly->GetPenWidth();
std::vector<VECTOR2I> points;
for( int idx = 0; idx < poly->GetPolygons().OutlineCount(); ++idx )
{
points.clear();
SHAPE_LINE_CHAIN& outline = poly->GetPolygons().Outline( idx );
for( int ii = 0; ii < outline.PointCount(); ii++ )
points.emplace_back( outline.CPoint( ii ).x, outline.CPoint( ii ).y );
plotter->PlotPoly( points, FILL_T::FILLED_SHAPE, penWidth );
}
}
break;
default:
wxFAIL_MSG( wxT( "PlotDrawingSheet(): Unknown drawing sheet item." ) );
break;
}
wxFAIL_MSG( wxT( "PlotDrawingSheet(): Exception during plot." ) );
}
}

View File

@ -658,10 +658,10 @@ protected:
FILL_T 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,
uint32_t 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.
uint32_t m_brush_rgb_color; // same as m_pen_rgb_color, used to fill some contours.
double m_brush_alpha;
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

View File

@ -213,9 +213,16 @@ bool PCB_PLOTTER::Plot( const wxString& aOutputPath,
plotter->SetSubject( msg );
}
PlotBoardLayers( m_board, plotter, plotSequence, m_plotOpts );
PlotInteractiveLayer( m_board, plotter, m_plotOpts );
try
{
PlotBoardLayers( m_board, plotter, plotSequence, m_plotOpts );
PlotInteractiveLayer( m_board, plotter, m_plotOpts );
}
catch( ... )
{
success = false;
break;
}
if( m_plotOpts.GetFormat() == PLOT_FORMAT::PDF && m_plotOpts.m_PDFSingle
&& i != layersToPlot.size() - 1 )
@ -247,7 +254,15 @@ bool PCB_PLOTTER::Plot( const wxString& aOutputPath,
|| i == aLayersToPlot.size() - 1
|| pageNum == finalPageCount )
{
plotter->EndPlot();
try
{
plotter->EndPlot();
}
catch( ... )
{
success = false;
}
delete plotter->RenderSettings();
delete plotter;
plotter = nullptr;

View File

@ -776,8 +776,6 @@ int PCBNEW_JOBS_HANDLER::JobExportSvg( JOB* aJob )
sheetPath = aSvgJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
}
LOCALE_IO dummy;
if( !plotter.Plot( outPath, aSvgJob->m_plotLayerSequence, aSvgJob->m_plotOnAllLayersSequence,
false, aSvgJob->m_genMode == JOB_EXPORT_PCB_SVG::GEN_MODE::SINGLE,
layerName, sheetName, sheetPath ) )
@ -1760,8 +1758,6 @@ int PCBNEW_JOBS_HANDLER::doFpExportSvg( JOB_FP_EXPORT_SVG* aSvgJob, const FOOTPR
PCB_PLOTTER plotter( brd.get(), m_reporter, plotOpts );
LOCALE_IO dummy;
if( !plotter.Plot( outputFile.GetFullPath(),
aSvgJob->m_plotLayerSequence,
aSvgJob->m_plotOnAllLayersSequence,

View File

@ -1315,14 +1315,21 @@ PLOTTER* StartPlotBoard( BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aL
}
bool startPlotSuccess = false;
if (plotter->GetPlotterType() == PLOT_FORMAT::PDF)
try
{
startPlotSuccess =
static_cast<PDF_PLOTTER*>( plotter )->StartPlot( aPageNumber, aPageName );
if( plotter->GetPlotterType() == PLOT_FORMAT::PDF )
{
startPlotSuccess =
static_cast<PDF_PLOTTER*>( plotter )->StartPlot( aPageNumber, aPageName );
}
else
{
startPlotSuccess = plotter->StartPlot( aPageName );
}
}
else
catch( ... )
{
startPlotSuccess = plotter->StartPlot( aPageName );
startPlotSuccess = false;
}