Add commenting regarding double-output of text.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/18090
This commit is contained in:
Jeff Young 2024-05-27 12:13:53 +01:00
parent 20e2dddc0b
commit 233ebb3e09
1 changed files with 119 additions and 53 deletions

View File

@ -396,15 +396,19 @@ void SVG_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int
{
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 );
m_precision, rect_dev.GetPosition().x,
m_precision, rect_dev.GetPosition().y,
m_precision, rect_dev.GetEnd().x,
m_precision, rect_dev.GetEnd().y );
}
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,
rect_dev.GetPosition().x,
rect_dev.GetPosition().y,
rect_dev.GetSize().x,
rect_dev.GetSize().y,
0.0 /* radius of rounded corners */ );
}
}
@ -432,7 +436,9 @@ void SVG_PLOTTER::Circle( const VECTOR2I& pos, int diametre, FILL_T fill, int wi
fprintf( m_outputFile,
"<circle cx=\"%.*f\" cy=\"%.*f\" r=\"%.*f\" /> \n",
m_precision, pos_dev.x, m_precision, pos_dev.y, m_precision, radius );
m_precision, pos_dev.x,
m_precision, pos_dev.y,
m_precision, radius );
}
@ -522,11 +528,16 @@ void SVG_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
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 );
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 );
}
setFillMode( FILL_T::NO_FILL );
@ -535,11 +546,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 );
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 );
}
@ -560,11 +576,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 );
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 );
#else
PLOTTER::BezierCurve( aStart, aControl1, aControl2, aEnd, aTolerance, aLineThickness );
#endif
@ -595,12 +616,18 @@ 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 );
fprintf( m_outputFile,
"d=\"M %.*f,%.*f\n",
m_precision, pos.x,
m_precision, pos.y );
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 );
fprintf( m_outputFile,
"%.*f,%.*f\n",
m_precision, pos.x,
m_precision, pos.y );
}
// If the corner list ends where it begins, then close the poly
@ -611,7 +638,10 @@ void SVG_PLOTTER::PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFi
else
{
pos = userToDeviceCoordinates( aCornerList.back() );
fprintf( m_outputFile, "%.*f,%.*f\n\" /> \n", m_precision, pos.x, m_precision, pos.y );
fprintf( m_outputFile,
"%.*f,%.*f\n\" /> \n",
m_precision, pos.x,
m_precision, pos.y );
}
}
@ -645,6 +675,7 @@ void SVG_PLOTTER::PlotImage( const wxImage& aImage, const VECTOR2I& aPos, double
wxImage image = aImage.ConvertToGreyscale();
image.SaveFile( img_stream, wxBITMAP_TYPE_PNG );
}
size_t input_len = img_stream.GetOutputStreamBuffer()->GetBufferSize();
std::vector<uint8_t> buffer( input_len );
std::vector<uint8_t> encoded;
@ -654,7 +685,8 @@ void SVG_PLOTTER::PlotImage( const wxImage& aImage, const VECTOR2I& aPos, double
fprintf( m_outputFile,
"<image x=\"%f\" y=\"%f\" xlink:href=\"data:image/png;base64,",
userToDeviceSize( start.x ), userToDeviceSize( start.y ) );
userToDeviceSize( start.x ),
userToDeviceSize( start.y ) );
for( size_t i = 0; i < encoded.size(); i++ )
{
@ -664,8 +696,12 @@ void SVG_PLOTTER::PlotImage( const wxImage& aImage, const VECTOR2I& aPos, double
fprintf( m_outputFile, "\n" );
}
fprintf( m_outputFile, "\"\npreserveAspectRatio=\"none\" width=\"%.*f\" height=\"%.*f\" />",
m_precision, userToDeviceSize( drawsize.x ), m_precision, userToDeviceSize( drawsize.y ) );
fprintf( m_outputFile,
"\"\npreserveAspectRatio=\"none\" width=\"%.*f\" height=\"%.*f\" />",
m_precision,
userToDeviceSize( drawsize.x ),
m_precision,
userToDeviceSize( drawsize.y ) );
}
}
@ -757,17 +793,24 @@ bool SVG_PLOTTER::StartPlot( const wxString& aPageNumber )
fprintf( m_outputFile,
"<title>SVG Image created as %s date %s </title>\n",
TO_UTF8( XmlEsc( wxFileName( m_filename ).GetFullName() ) ), date_buf );
TO_UTF8( XmlEsc( wxFileName( m_filename ).GetFullName() ) ),
date_buf );
// End of header
fprintf( m_outputFile, " <desc>Image generated by %s </desc>\n",
fprintf( m_outputFile,
" <desc>Image generated by %s </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 );
m_brush_rgb_color,
m_precision,
m_brush_alpha,
m_pen_rgb_color,
m_precision,
opacity );
// output the pen cap and line joint
fputs( "stroke-linecap:round; stroke-linejoin:round;\"\n", m_outputFile );
@ -841,35 +884,58 @@ void SVG_PLOTTER::Text( const VECTOR2I& aPos,
VECTOR2D text_pos_dev = userToDeviceCoordinates( text_pos );
VECTOR2D sz_dev = userToDeviceSize( text_size );
if( !aOrient.IsZero() )
// Output the text as a string for search (and for screen readers that fail to pay attention
// to <desc> tags).
{
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 );
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 );
}
fprintf( m_outputFile,
"<text x=\"%.*f\" y=\"%.*f\"\n",
m_precision,
text_pos_dev.x, m_precision,
text_pos_dev.y );
/// 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 );
}
fprintf( m_outputFile,
"textLength=\"%.*f\" font-size=\"%.*f\" lengthAdjust=\"spacingAndGlyphs\"\n"
"text-anchor=\"%s\" opacity=\"0\">%s</text>\n",
m_precision,
sz_dev.x,
m_precision,
sz_dev.y,
hjust,
TO_UTF8( XmlEsc( aText ) ) );
if( !aOrient.IsZero() )
fputs( "</g>\n", m_outputFile );
}
fprintf( m_outputFile, "<text x=\"%.*f\" y=\"%.*f\"\n",
m_precision, text_pos_dev.x, m_precision, text_pos_dev.y );
// Output the text again as graphics (with a <desc> tag for "proper" screen readers)
{
fprintf( m_outputFile,
"<g class=\"stroked-text\"><desc>%s</desc>\n",
TO_UTF8( XmlEsc( aText ) ) );
/// 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 );
PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, aWidth,
aItalic, aBold, aMultilineAllowed, aFont, aFontMetrics );
fprintf( m_outputFile,
"textLength=\"%.*f\" font-size=\"%.*f\" lengthAdjust=\"spacingAndGlyphs\"\n"
"text-anchor=\"%s\" opacity=\"0\">%s</text>\n",
m_precision, sz_dev.x, m_precision, sz_dev.y, hjust, TO_UTF8( XmlEsc( aText ) ) );
if( !aOrient.IsZero() )
fputs( "</g>\n", m_outputFile );
fprintf( m_outputFile, "<g class=\"stroked-text\"><desc>%s</desc>\n",
TO_UTF8( XmlEsc( aText ) ) );
PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, aWidth, aItalic,
aBold, aMultilineAllowed, aFont, aFontMetrics );
fputs( "</g>", m_outputFile );
fputs( "</g>", m_outputFile );
}
}