From 8f30404e4290a4744927f1418e89e5c826a89cee Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Tue, 17 Aug 2021 13:44:11 -0400 Subject: [PATCH] Plot code cleaning. --- common/plotters/HPGL_plotter.cpp | 64 +++++++++---------- common/plotters/PDF_plotter.cpp | 5 +- common/plotters/PS_plotter.cpp | 27 +++++--- common/plotters/SVG_plotter.cpp | 10 +-- common/plotters/common_plot_functions.cpp | 76 +++++++++++------------ common/plotters/plotter.cpp | 19 ++++-- common/plotters/plotter_hpgl.h | 39 ++++++------ common/plotters/plotters_pslike.h | 2 +- 8 files changed, 132 insertions(+), 110 deletions(-) diff --git a/common/plotters/HPGL_plotter.cpp b/common/plotters/HPGL_plotter.cpp index 8f1100e43e..f44d7d21c8 100644 --- a/common/plotters/HPGL_plotter.cpp +++ b/common/plotters/HPGL_plotter.cpp @@ -24,10 +24,10 @@ /** * @file HPGL_plotter.cpp - * @brief Kicad: specialized plotter for HPGL files format + * @brief KiCad plotter for HPGL file format. * Since this plot engine is mostly intended for import in external programs, * sadly HPGL/2 isn't supported a lot... some of the primitives use overlapped - * strokes to fill the shape + * strokes to fill the shape. */ /* Some HPGL commands: @@ -195,7 +195,6 @@ #include -#include #include #include #include @@ -206,7 +205,7 @@ /// Compute the distance between two DPOINT points. -static double dpoint_dist( DPOINT a, DPOINT b ); +static double dpoint_dist( const DPOINT& a, const DPOINT& b ); // The hpgl command to close a polygon def, fill it and plot outline: @@ -215,10 +214,12 @@ static double dpoint_dist( DPOINT a, DPOINT b ); // EP; draws the polygon outline. It usually gives a better look to the filled polygon static const char hpgl_end_polygon_cmd[] = "PM 2; FP; EP;\n"; + // HPGL scale factor (1 Plotter Logical Unit = 1/40mm = 25 micrometers) // PLUsPERDECIMIL = (25.4 / 10000) / 0.025 static const double PLUsPERDECIMIL = 0.1016; + HPGL_PLOTTER::HPGL_PLOTTER() : arcTargetChordLength( 0 ), arcMinChordDegrees( 5.0 ), @@ -232,6 +233,7 @@ HPGL_PLOTTER::HPGL_PLOTTER() SetPenDiameter( 0.0 ); } + void HPGL_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil, double aScale, bool aMirror ) { @@ -240,7 +242,7 @@ void HPGL_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil, m_IUsPerDecimil = aIusPerDecimil; m_iuPerDeviceUnit = PLUsPERDECIMIL / aIusPerDecimil; - /* Compute the paper size in IUs */ + // Compute the paper size in IUs. m_paperSize = m_pageInfo.GetSizeMils(); m_paperSize.x *= 10.0 * aIusPerDecimil; m_paperSize.y *= 10.0 * aIusPerDecimil; @@ -331,6 +333,7 @@ bool HPGL_PLOTTER::EndPlot() fputs( "PU;", m_outputFile ); pen_up = true; } + fprintf( m_outputFile, "SP%d;", item.pen ); current_pen = item.pen; } @@ -428,11 +431,11 @@ void HPGL_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_TYPE fill, // Draw the filled area MoveTo( centre ); startOrAppendItem( center_dev, wxString::Format( "PM 0;CI %g,%g;%s", radius, chord_degrees, - hpgl_end_polygon_cmd ) ); + hpgl_end_polygon_cmd ) ); m_current_item->lift_before = true; m_current_item->pen_returns = true; - m_current_item->bbox.Merge( - BOX2D( center_dev - radius, VECTOR2D( 2 * radius, 2 * radius ) ) ); + m_current_item->bbox.Merge( BOX2D( center_dev - radius, + VECTOR2D( 2 * radius, 2 * radius ) ) ); PenFinish(); } @@ -442,8 +445,8 @@ void HPGL_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_TYPE fill, startOrAppendItem( center_dev, wxString::Format( "CI %g,%g;", radius, chord_degrees ) ); m_current_item->lift_before = true; m_current_item->pen_returns = true; - m_current_item->bbox.Merge( - BOX2D( center_dev - radius, VECTOR2D( 2 * radius, 2 * radius ) ) ); + m_current_item->bbox.Merge( BOX2D( center_dev - radius, + VECTOR2D( 2 * radius, 2 * radius ) ) ); PenFinish(); } } @@ -526,14 +529,7 @@ void HPGL_PLOTTER::PenTo( const wxPoint& pos, char plume ) else if( plume == 'D' ) { m_penState = 'D'; - startOrAppendItem( - lastpos_dev, - wxString::Format( - "PA %.0f,%.0f;", - pos_dev.x, - pos_dev.y - ) - ); + startOrAppendItem( lastpos_dev, wxString::Format( "PA %.0f,%.0f;", pos_dev.x, pos_dev.y ) ); m_current_item->loc_end = pos_dev; m_current_item->bbox.Merge( pos_dev ); } @@ -607,11 +603,11 @@ void HPGL_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, DPOINT cmap_dev = userToDeviceCoordinates( cmap ); startOrAppendItem( cmap_dev, wxString::Format( "AA %.0f,%.0f,%.0f,%g", centre_dev.x, - centre_dev.y, angle, chord_degrees ) ); + centre_dev.y, angle, chord_degrees ) ); // TODO We could compute the final position and full bounding box instead... - m_current_item->bbox.Merge( - BOX2D( centre_dev - radius_dev, VECTOR2D( radius_dev * 2, radius_dev * 2 ) ) ); + m_current_item->bbox.Merge( BOX2D( centre_dev - radius_dev, + VECTOR2D( radius_dev * 2, radius_dev * 2 ) ) ); m_current_item->lift_after = true; flushItem(); } @@ -676,10 +672,11 @@ void HPGL_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, // A filled polygon uses always the current point to start the polygon. // Gives a correct current starting point for the circle MoveTo( wxPoint( pos.x+radius, pos.y ) ); + // Plot filled area and its outline startOrAppendItem( userToDeviceCoordinates( wxPoint( pos.x + radius, pos.y ) ), - wxString::Format( "PM 0; PA %.0f,%.0f;CI %.0f;%s", pos_dev.x, pos_dev.y, rsize, - hpgl_end_polygon_cmd ) ); + wxString::Format( "PM 0; PA %.0f,%.0f;CI %.0f;%s", + pos_dev.x, pos_dev.y, rsize, hpgl_end_polygon_cmd ) ); m_current_item->lift_before = true; m_current_item->pen_returns = true; } @@ -719,6 +716,7 @@ void HPGL_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize, corners.emplace_back( - dx, + dy ); corners.emplace_back( + dx, + dy ); corners.emplace_back( + dx, - dy ); + // Close polygon corners.emplace_back( - dx, - dy ); @@ -742,8 +740,7 @@ void HPGL_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSiz if( aTraceMode == FILLED ) { - // in filled mode, the pen diameter is removed from size - // to keep the pad size + // In filled mode, the pen diameter is removed from size to keep the pad size. size.x -= KiROUND( penDiameter ) / 2; size.x = std::max( size.x, 0); size.y -= KiROUND( penDiameter ) / 2; @@ -770,9 +767,9 @@ void HPGL_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSiz PlotPoly( cornerList, aTraceMode == FILLED ? FILL_TYPE::FILLED_SHAPE : FILL_TYPE::NO_FILL ); } -void HPGL_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, - double aOrient, SHAPE_POLY_SET* aPolygons, - OUTLINE_MODE aTraceMode, void* aData ) + +void HPGL_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, double aOrient, + SHAPE_POLY_SET* aPolygons, OUTLINE_MODE aTraceMode, void* aData ) { std::vector< wxPoint > cornerList; @@ -823,7 +820,7 @@ void HPGL_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos, int aRadius, i } -bool HPGL_PLOTTER::startItem( DPOINT location ) +bool HPGL_PLOTTER::startItem( const DPOINT& location ) { return startOrAppendItem( location, wxEmptyString ); } @@ -835,7 +832,7 @@ void HPGL_PLOTTER::flushItem() } -bool HPGL_PLOTTER::startOrAppendItem( DPOINT location, wxString const& content ) +bool HPGL_PLOTTER::startOrAppendItem( const DPOINT& location, wxString const& content ) { if( m_current_item == nullptr ) { @@ -874,7 +871,7 @@ void HPGL_PLOTTER::sortItems( std::list& items ) // 2) Within the items for one pen, avoid bouncing back and forth around // the page; items should be sequenced with nearby items. // - // This is essentially a variant of the Travelling Salesman Problem where + // This is essentially a variant of the Traveling Salesman Problem where // the cities are themselves edges that must be traversed. This is of course // a famously NP-Hard problem and this particular variant has a monstrous // number of "cities". For now, we're using a naive nearest-neighbor search, @@ -897,8 +894,7 @@ void HPGL_PLOTTER::sortItems( std::list& items ) for( auto search_it = best_it; search_it != items.end(); search_it++ ) { - // Immediately forget an item as "best" if another one is a better - // pen match + // Immediately forget an item as "best" if another one is a better pen match if( best_it->pen != last_item.pen && search_it->pen == last_item.pen ) { best_it = search_it; @@ -944,7 +940,7 @@ const char* HPGL_PLOTTER::lineTypeCommand( PLOT_DASH_TYPE linetype ) } -static double dpoint_dist( DPOINT a, DPOINT b ) +static double dpoint_dist( const DPOINT& a, const DPOINT& b ) { DPOINT diff = a - b; return sqrt( diff.x * diff.x + diff.y * diff.y ); diff --git a/common/plotters/PDF_plotter.cpp b/common/plotters/PDF_plotter.cpp index a83ee59a8d..f59d22457d 100644 --- a/common/plotters/PDF_plotter.cpp +++ b/common/plotters/PDF_plotter.cpp @@ -363,7 +363,7 @@ void PDF_PLOTTER::PenTo( const wxPoint& pos, char plume ) } -void PDF_PLOTTER::PlotImage( const wxImage & aImage, const wxPoint& aPos, double aScaleFactor ) +void PDF_PLOTTER::PlotImage( const wxImage& aImage, const wxPoint& aPos, double aScaleFactor ) { wxASSERT( workFile ); wxSize pix_size( aImage.GetWidth(), aImage.GetHeight() ); @@ -663,8 +663,7 @@ bool PDF_PLOTTER::StartPlot() that they must have the bit 7 set) */ fputs( "%PDF-1.5\n%\200\201\202\203\n", m_outputFile ); - /* Allocate an entry for the page tree root, it will go in every page - parent entry */ + /* 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 diff --git a/common/plotters/PS_plotter.cpp b/common/plotters/PS_plotter.cpp index 64dfbf2c11..4a8a005ff4 100644 --- a/common/plotters/PS_plotter.cpp +++ b/common/plotters/PS_plotter.cpp @@ -24,7 +24,7 @@ /** * @file PS_plotter.cpp - * @brief Kicad: specialized plotter for PS files format + * @brief KiCad: specialized plotter for PS files format */ #include @@ -77,8 +77,10 @@ void PSLIKE_PLOTTER::SetColor( const COLOR4D& color ) * holes in white on pads in black */ double k = 1; // White + if( color != COLOR4D::WHITE ) k = 0; + if( m_negativeMode ) emitSetRGBColor( 1 - k, 1 - k, 1 - k ); else @@ -189,6 +191,7 @@ void PSLIKE_PLOTTER::FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize, GetCurrentLineWidth() ); } + void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, OUTLINE_MODE aTraceMode, void* aData ) @@ -204,7 +207,7 @@ void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); size.x -= GetCurrentLineWidth(); size.y -= GetCurrentLineWidth(); - aCornerRadius -= GetCurrentLineWidth()/2; + aCornerRadius -= GetCurrentLineWidth() / 2; } @@ -213,6 +216,7 @@ void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS 0.0, 0, 0, GetPlotterArcHighDef(), ERROR_INSIDE ); std::vector< wxPoint > cornerList; + // TransformRoundRectToPolygon creates only one convex polygon SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); cornerList.reserve( poly.PointCount() ); @@ -227,6 +231,7 @@ void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS GetCurrentLineWidth() ); } + void PSLIKE_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, double aOrient, SHAPE_POLY_SET* aPolygons, OUTLINE_MODE aTraceMode, void* aData ) @@ -263,6 +268,7 @@ void PSLIKE_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize } } + void PSLIKE_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, double aPadOrient, OUTLINE_MODE aTraceMode, void* aData ) { @@ -280,6 +286,7 @@ void PSLIKE_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCor { SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); int w = GetCurrentLineWidth(); + // offset polygon by w // coord[0] is assumed the lower left // coord[1] is assumed the upper left @@ -333,10 +340,11 @@ std::string PSLIKE_PLOTTER::encodeStringForPlotter( const wxString& aUnicode ) { switch (ch) { - // The ~ shouldn't reach the outside + // The ~ shouldn't reach the outside case '~': break; - // These characters must be escaped + + // These characters must be escaped case '(': case ')': case '\\': @@ -366,15 +374,15 @@ int PSLIKE_PLOTTER::returnPostscriptTextWidth( const wxString& aText, int aXSize for( unsigned i = 0; i < aText.length(); i++ ) { wchar_t AsciiCode = aText[i]; - // Skip the negation marks and untabled points + + // Skip the negation marks and untabled points. if( AsciiCode != '~' && AsciiCode < 256 ) { tally += width_table[AsciiCode]; } } - // Widths are proportional to height, but height is enlarged by a - // scaling factor + // Widths are proportional to height, but height is enlarged by a scaling factor. return KiROUND( aXSize * tally / postscriptTextAscent ); } @@ -392,6 +400,7 @@ void PSLIKE_PLOTTER::postscriptOverlinePositions( const wxString& aText, int aXS for( unsigned i = 0; i < aText.length(); i++ ) { wchar_t AsciiCode = aText[i]; + // Skip the negation marks and untabled points if( AsciiCode != '~' && AsciiCode < 256 ) { @@ -419,6 +428,7 @@ void PS_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil, m_plotScale = aScale; m_IUsPerDecimil = aIusPerDecimil; m_iuPerDeviceUnit = 1.0 / aIusPerDecimil; + /* Compute the paper size in IUs */ m_paperSize = m_pageInfo.GetSizeMils(); m_paperSize.x *= 10.0 * aIusPerDecimil; @@ -674,6 +684,7 @@ void PS_PLOTTER::PlotImage( const wxImage& aImage, const wxPoint& aPos, double a // Locate lower-left corner of image DPOINT start_dev = userToDeviceCoordinates( start ); fprintf( m_outputFile, "%g %g translate\n", start_dev.x, start_dev.y ); + // Map image size to device DPOINT end_dev = userToDeviceCoordinates( end ); fprintf( m_outputFile, "%g %g scale\n", @@ -681,8 +692,10 @@ void PS_PLOTTER::PlotImage( const wxImage& aImage, const wxPoint& aPos, double a // Dimensions of source image (in pixels fprintf( m_outputFile, "%d %d 8", pix_size.x, pix_size.y ); + // Map unit square to source fprintf( m_outputFile, " [%d 0 0 %d 0 %d]\n", pix_size.x, -pix_size.y , pix_size.y); + // include image data in ps file fprintf( m_outputFile, "{currentfile pix readhexstring pop}\n" ); diff --git a/common/plotters/SVG_plotter.cpp b/common/plotters/SVG_plotter.cpp index 89df75a3b4..2e4ee75c2b 100644 --- a/common/plotters/SVG_plotter.cpp +++ b/common/plotters/SVG_plotter.cpp @@ -1,6 +1,6 @@ /** * @file SVG_plotter.cpp - * @brief Kicad: specialized plotter for SVG files format + * @brief KiCad: specialized plotter for SVG files format */ /* @@ -193,6 +193,7 @@ void SVG_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil, SetSvgCoordinatesFormat( 4, true ); } + void SVG_PLOTTER::SetSvgCoordinatesFormat( unsigned aResolution, bool aUseInches ) { m_useInch = aUseInches; @@ -355,8 +356,7 @@ void SVG_PLOTTER::emitSetRGBColor( double r, double g, double b ) m_graphics_changed = true; m_pen_rgb_color = rgb_color; - // Currently, use the same color for brush and pen - // (i.e. to draw and fill a contour) + // Currently, use the same color for brush and pen (i.e. to draw and fill a contour). m_brush_rgb_color = rgb_color; } } @@ -382,6 +382,7 @@ void SVG_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, in DPOINT org_dev = userToDeviceCoordinates( rect.GetOrigin() ); DPOINT end_dev = userToDeviceCoordinates( rect.GetEnd() ); DSIZE size_dev = end_dev - org_dev; + // Ensure size of rect in device coordinates is > 0 // I don't know if this is a SVG issue or a Inkscape issue, but // Inkscape has problems with negative or null values for width and/or height, so avoid them @@ -554,7 +555,7 @@ void SVG_PLOTTER::BezierCurve( const wxPoint& aStart, const wxPoint& aControl1, start.x, start.y, ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, end.x, end.y ); #else - PLOTTER::BezierCurve( aStart, aControl1,aControl2, aEnd,aTolerance, aLineThickness ); + PLOTTER::BezierCurve( aStart, aControl1, aControl2, aEnd, aTolerance, aLineThickness ); #endif } @@ -811,6 +812,7 @@ void SVG_PLOTTER::Text( const wxPoint& aPos, } wxSize text_size; + // aSize.x or aSize.y is < 0 for mirrored texts. // The actual text size value is the absolute value text_size.x = std::abs( GraphicTextWidth( aText, aSize, aItalic, aWidth ) ); diff --git a/common/plotters/common_plot_functions.cpp b/common/plotters/common_plot_functions.cpp index 880d848e15..ff7f3f8103 100644 --- a/common/plotters/common_plot_functions.cpp +++ b/common/plotters/common_plot_functions.cpp @@ -94,63 +94,63 @@ void PlotDrawingSheet( PLOTTER* plotter, const PROJECT* aProject, const TITLE_BL 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() ); - } + { + 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; - int penWidth = std::max( rect->GetPenWidth(), defaultPenWidth ); - plotter->Rect( rect->GetStart(), rect->GetEnd(), FILL_TYPE::NO_FILL, penWidth ); - } + { + DS_DRAW_ITEM_RECT* rect = (DS_DRAW_ITEM_RECT*) item; + int penWidth = std::max( rect->GetPenWidth(), defaultPenWidth ); + plotter->Rect( rect->GetStart(), rect->GetEnd(), FILL_TYPE::NO_FILL, penWidth ); + } break; case WSG_TEXT_T: - { - DS_DRAW_ITEM_TEXT* text = (DS_DRAW_ITEM_TEXT*) item; - int penWidth = std::max( text->GetEffectiveTextPenWidth(), defaultPenWidth ); - plotter->Text( text->GetTextPos(), plotColor, text->GetShownText(), - text->GetTextAngle(), text->GetTextSize(), text->GetHorizJustify(), - text->GetVertJustify(), penWidth, text->IsItalic(), text->IsBold(), - text->IsMultilineAllowed() ); - } + { + DS_DRAW_ITEM_TEXT* text = (DS_DRAW_ITEM_TEXT*) item; + int penWidth = std::max( text->GetEffectiveTextPenWidth(), defaultPenWidth ); + plotter->Text( text->GetTextPos(), plotColor, text->GetShownText(), + text->GetTextAngle(), text->GetTextSize(), text->GetHorizJustify(), + text->GetVertJustify(), penWidth, text->IsItalic(), text->IsBold(), + text->IsMultilineAllowed() ); + } break; case WSG_POLY_T: + { + DS_DRAW_ITEM_POLYPOLYGONS* poly = (DS_DRAW_ITEM_POLYPOLYGONS*) item; + int penWidth = std::max( poly->GetPenWidth(), defaultPenWidth ); + std::vector points; + + for( int idx = 0; idx < poly->GetPolygons().OutlineCount(); ++idx ) { - DS_DRAW_ITEM_POLYPOLYGONS* poly = (DS_DRAW_ITEM_POLYPOLYGONS*) item; - int penWidth = std::max( poly->GetPenWidth(), defaultPenWidth ); - std::vector points; + points.clear(); + SHAPE_LINE_CHAIN& outline = poly->GetPolygons().Outline( idx ); - 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 ); - for( int ii = 0; ii < outline.PointCount(); ii++ ) - points.emplace_back( outline.CPoint( ii ).x, outline.CPoint( ii ).y ); - - plotter->PlotPoly( points, FILL_TYPE::FILLED_SHAPE, penWidth ); - } + plotter->PlotPoly( points, FILL_TYPE::FILLED_SHAPE, penWidth ); } + } break; case WSG_BITMAP_T: - { - DS_DRAW_ITEM_BITMAP* drawItem = (DS_DRAW_ITEM_BITMAP*) item; - DS_DATA_ITEM_BITMAP* bitmap = (DS_DATA_ITEM_BITMAP*) drawItem->GetPeer(); + { + 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 ) - break; + if( bitmap->m_ImageBitmap == nullptr ) + break; - bitmap->m_ImageBitmap->PlotImage( plotter, drawItem->GetPosition(), plotColor, + bitmap->m_ImageBitmap->PlotImage( plotter, drawItem->GetPosition(), plotColor, PLOTTER::USE_DEFAULT_LINE_WIDTH ); - } + } break; default: diff --git a/common/plotters/plotter.cpp b/common/plotters/plotter.cpp index 5c96fb9048..84311ed736 100644 --- a/common/plotters/plotter.cpp +++ b/common/plotters/plotter.cpp @@ -47,6 +47,7 @@ #include #include // for KiROUND + PLOTTER::PLOTTER( ) { m_plotScale = 1; @@ -58,16 +59,17 @@ PLOTTER::PLOTTER( ) m_outputFile = nullptr; m_colorMode = false; // Starts as a BW plot m_negativeMode = false; + // Temporary init to avoid not initialized vars, will be set later m_IUsPerDecimil = 1; // will be set later to the actual value m_iuPerDeviceUnit = 1; // will be set later to the actual value m_renderSettings = nullptr; } + PLOTTER::~PLOTTER() { - // Emergency cleanup, but closing the file is - // usually made in EndPlot(). + // Emergency cleanup, but closing the file is usually made in EndPlot(). if( m_outputFile ) fclose( m_outputFile ); } @@ -79,8 +81,7 @@ bool PLOTTER::OpenFile( const wxString& aFullFilename ) wxASSERT( !m_outputFile ); - // Open the file in text mode (not suitable for all plotters - // but only for most of them + // Open the file in text mode (not suitable for all plotters but only for most of them. m_outputFile = wxFopen( m_filename, wxT( "wt" ) ); if( m_outputFile == nullptr ) @@ -172,6 +173,7 @@ void PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int r std::swap( StAngle, EndAngle ); SetCurrentLineWidth( width ); + /* Please NOTE the different sign due to Y-axis flip */ start.x = centre.x + KiROUND( cosdecideg( radius, -StAngle ) ); start.y = centre.y + KiROUND( sindecideg( radius, -StAngle ) ); @@ -236,7 +238,7 @@ void PLOTTER::BezierCurve( const wxPoint& aStart, const wxPoint& aControl1, } -void PLOTTER::PlotImage(const wxImage & aImage, const wxPoint& aPos, double aScaleFactor ) +void PLOTTER::PlotImage(const wxImage& aImage, const wxPoint& aPos, double aScaleFactor ) { wxSize size( aImage.GetWidth() * aScaleFactor, aImage.GetHeight() * aScaleFactor ); @@ -356,6 +358,7 @@ void PLOTTER::Marker( const wxPoint& position, int diametre, unsigned aShapeId ) 0014, // + 0040, // Sq 0020, // Lz + // Two simple shapes 0103, // X O 0017, // X + @@ -367,6 +370,7 @@ void PLOTTER::Marker( const wxPoint& position, int diametre, unsigned aShapeId ) 0054, // + Sq 0034, // + Lz 0060, // Sq Lz + // Three simple shapes 0117, // X O + 0143, // X O Sq @@ -377,14 +381,17 @@ void PLOTTER::Marker( const wxPoint& position, int diametre, unsigned aShapeId ) 0154, // O + Sq 0134, // O + Lz 0074, // + Sq Lz + // Four simple shapes 0174, // O Sq Lz + 0163, // X O Sq Lz 0157, // X O Sq + 0137, // X O Lz + 0077, // X Sq Lz + + // This draws *everything * 0177, // X O Sq Lz + + // Here we use the single bars... so the cross is forbidden 0110, // O - 0104, // O | @@ -407,6 +414,7 @@ void PLOTTER::Marker( const wxPoint& position, int diametre, unsigned aShapeId ) 0170, // O Sq Lz - 0164, // O Sq Lz | 0161, // O Sq Lz / + // Last resort: the backlash component (easy to confound) 0102, // \ O 0042, // \ Sq @@ -416,6 +424,7 @@ void PLOTTER::Marker( const wxPoint& position, int diametre, unsigned aShapeId ) 0062, // \ Sq Lz 0162 // \ O Sq Lz }; + if( aShapeId >= MARKER_COUNT ) { // Fallback shape diff --git a/common/plotters/plotter_hpgl.h b/common/plotters/plotter_hpgl.h index e325b2fa3a..40bec3f30b 100644 --- a/common/plotters/plotter_hpgl.h +++ b/common/plotters/plotter_hpgl.h @@ -47,10 +47,11 @@ public: return wxString( wxT( "plt" ) ); } - /// Set the target length of chords used to draw approximated circles and - /// arcs. - /// - /// @param chord_len - chord length in IUs + /** + * Set the target length of chords used to draw approximated circles and arcs. + * + * @param chord_len the chord length in IUs. + */ void SetTargetChordLength( double chord_len ); /// Switch to the user coordinate system @@ -143,24 +144,26 @@ public: void* aData ) override; protected: - /// Start a new HPGL_ITEM if necessary, keeping the current one if it exists. - /// - /// @param location is the location of the item. - /// - /// @return whether a new item was made. - bool startItem( DPOINT location ); + /** + * Start a new HPGL_ITEM if necessary, keeping the current one if it exists. + * + * @param location is the location of the item. + * @return whether a new item was made. + */ + bool startItem( const DPOINT& location ); /// Flush the current HPGL_ITEM and clear out the current item pointer. void flushItem(); - /// Start a new HPGL_ITEM with the given string if necessary, or append the - /// string to the current item. - /// - /// @param location is the location of the item, if a new one is made. - /// @param content is the content substring. - /// - /// @return whether a new item was made - bool startOrAppendItem( DPOINT location, const wxString& content ); + /** + * Start a new HPGL_ITEM with the given string if necessary, or append the + * string to the current item. + * + * @param location is the location of the item, if a new one is made. + * @param content is the content substring. + * @return whether a new item was made. + */ + bool startOrAppendItem( const DPOINT& location, const wxString& content ); int penSpeed; int penNumber; diff --git a/common/plotters/plotters_pslike.h b/common/plotters/plotters_pslike.h index 1c406179cb..21c41e90cf 100644 --- a/common/plotters/plotters_pslike.h +++ b/common/plotters/plotters_pslike.h @@ -443,7 +443,7 @@ public: virtual void SetDash( PLOT_DASH_TYPE dashed ) override; virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil, - double aScale, bool aMirror ) override; + 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,