diff --git a/bitmap2component/bitmap2cmp_gui.cpp b/bitmap2component/bitmap2cmp_gui.cpp index 3a0e84b94d..1759b6b8df 100644 --- a/bitmap2component/bitmap2cmp_gui.cpp +++ b/bitmap2component/bitmap2cmp_gui.cpp @@ -2,7 +2,7 @@ * This program source code file is part of KICAD, a free EDA CAD application. * * Copyright (C) 1992-2010 jean-pierre.charras - * Copyright (C) 1992-2019 Kicad Developers, see change_log.txt for contributors. + * Copyright (C) 1992-2019 Kicad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -56,9 +57,6 @@ #define DEFAULT_DPI 300 // Default resolution in Bit per inches -extern int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile, - OUTPUT_FMT_ID aFormat, int aDpi_X, int aDpi_Y, - BMP2CMP_MOD_LAYER aModLayer ); /** * Class BM2CMP_FRAME_BASE @@ -81,6 +79,7 @@ private: wxSize m_frameSize; wxPoint m_framePos; std::unique_ptr m_config; + bool m_exportToClipboard; public: BM2CMP_FRAME( KIWAY* aKiway, wxWindow* aParent ); @@ -96,23 +95,24 @@ private: void OnPaintGreyscale( wxPaintEvent& event ) override; void OnPaintBW( wxPaintEvent& event ) override; void OnLoadFile( wxCommandEvent& event ) override; - void OnExport( wxCommandEvent& event ) override; + void OnExportToFile( wxCommandEvent& event ) override; + void OnExportToClipboard( wxCommandEvent& event ) override; /** * Generate a schematic library which contains one component: * the logo */ - void OnExportEeschema(); + void exportEeschemaFormat(); /** * Generate a module in S expr format */ - void OnExportPcbnew(); + void exportPcbnewFormat(); /** * Generate a postscript file */ - void OnExportPostScript(); + void exportPostScriptFormat(); /** * Generate a file suitable to be copied into a page layout @@ -141,9 +141,16 @@ private: } void NegateGreyscaleImage( ); - void ExportFile( FILE* aOutfile, OUTPUT_FMT_ID aFormat ); + /** + * generate a export data of the current bitmap. + * @param aOutput is a string buffer to fill with data + * @param aFormat is the format to generate + */ + void ExportToBuffer( std::string&aOutput, OUTPUT_FMT_ID aFormat ); + void updateImageInfo(); void OnFormatChange( wxCommandEvent& event ) override; + void exportBitmap( OUTPUT_FMT_ID aFormat ); }; @@ -167,6 +174,7 @@ BM2CMP_FRAME::BM2CMP_FRAME( KIWAY* aKiway, wxWindow* aParent ) : m_config->Read( KEYWORD_BW_NEGATIVE, &tmp, 0 ); m_Negative = tmp != 0; m_checkNegative->SetValue( m_Negative ); + m_exportToClipboard = false; if( m_config->Read( KEYWORD_LAST_FORMAT, &tmp ) ) { @@ -198,7 +206,8 @@ BM2CMP_FRAME::BM2CMP_FRAME( KIWAY* aKiway, wxWindow* aParent ) : SetSize( m_framePos.x, m_framePos.y, m_frameSize.x, m_frameSize.y ); - m_buttonExport->Enable( false ); + m_buttonExportFile->Enable( false ); + m_buttonExportClipboard->Enable( false ); m_imageDPI.x = m_imageDPI.y = DEFAULT_DPI; // Default resolution in Bit per inches @@ -390,7 +399,9 @@ bool BM2CMP_FRAME::OpenProjectFiles( const std::vector& aFileSet, int m_NB_Image = m_Greyscale_Image; Binarize( (double) m_sliderThreshold->GetValue()/m_sliderThreshold->GetMax() ); - m_buttonExport->Enable( true ); + m_buttonExportFile->Enable( true ); + m_buttonExportClipboard->Enable( true ); + return true; } @@ -502,24 +513,53 @@ void BM2CMP_FRAME::OnThresholdChange( wxScrollEvent& event ) } -void BM2CMP_FRAME::OnExport( wxCommandEvent& event ) +void BM2CMP_FRAME::OnExportToFile( wxCommandEvent& event ) { + m_exportToClipboard = false; // choices of m_radioBoxFormat are expected to be in same order as // OUTPUT_FMT_ID. See bitmap2component.h - OUTPUT_FMT_ID sel = (OUTPUT_FMT_ID) m_radioBoxFormat->GetSelection(); + OUTPUT_FMT_ID format = (OUTPUT_FMT_ID) m_radioBoxFormat->GetSelection(); + exportBitmap( format ); +} - switch( sel ) + +void BM2CMP_FRAME::OnExportToClipboard( wxCommandEvent& event ) +{ + m_exportToClipboard = true; + // choices of m_radioBoxFormat are expected to be in same order as + // OUTPUT_FMT_ID. See bitmap2component.h + OUTPUT_FMT_ID format = (OUTPUT_FMT_ID) m_radioBoxFormat->GetSelection(); + + std::string buffer; + ExportToBuffer( buffer, format ); + + // Write buffer to the clipboard + if (wxTheClipboard->Open()) + { + // This data objects are held by the clipboard, + // so do not delete them in the app. + wxTheClipboard->SetData( new wxTextDataObject( buffer.c_str() ) ); + wxTheClipboard->Close(); + } + else + wxMessageBox( _( " Unable to export to the Clipboard") ); +} + + +void BM2CMP_FRAME::exportBitmap( OUTPUT_FMT_ID aFormat ) +{ + switch( aFormat ) { case EESCHEMA_FMT: - OnExportEeschema(); + exportEeschemaFormat(); break; case PCBNEW_KICAD_MOD: - OnExportPcbnew(); + exportPcbnewFormat(); break; case POSTSCRIPT_FMT: - OnExportPostScript(); + exportPostScriptFormat(); break; case KICAD_LOGO: @@ -560,12 +600,14 @@ void BM2CMP_FRAME::OnExportLogo() return; } - ExportFile( outfile, KICAD_LOGO ); + std::string buffer; + ExportToBuffer( buffer, KICAD_LOGO ); + fputs( buffer.c_str(), outfile ); fclose( outfile ); } -void BM2CMP_FRAME::OnExportPostScript() +void BM2CMP_FRAME::exportPostScriptFormat() { wxFileName fn( m_ConvertedFileName ); wxString path = fn.GetPath(); @@ -598,12 +640,14 @@ void BM2CMP_FRAME::OnExportPostScript() return; } - ExportFile( outfile, POSTSCRIPT_FMT ); + std::string buffer; + ExportToBuffer( buffer, POSTSCRIPT_FMT ); + fputs( buffer.c_str(), outfile ); fclose( outfile ); } -void BM2CMP_FRAME::OnExportEeschema() +void BM2CMP_FRAME::exportEeschemaFormat() { wxFileName fn( m_ConvertedFileName ); wxString path = fn.GetPath(); @@ -635,12 +679,14 @@ void BM2CMP_FRAME::OnExportEeschema() return; } - ExportFile( outfile, EESCHEMA_FMT ); + std::string buffer; + ExportToBuffer( buffer, EESCHEMA_FMT ); + fputs( buffer.c_str(), outfile ); fclose( outfile ); } -void BM2CMP_FRAME::OnExportPcbnew() +void BM2CMP_FRAME::exportPcbnewFormat() { wxFileName fn( m_ConvertedFileName ); wxString path = fn.GetPath(); @@ -672,13 +718,15 @@ void BM2CMP_FRAME::OnExportPcbnew() return; } - ExportFile( outfile, PCBNEW_KICAD_MOD ); + std::string buffer; + ExportToBuffer( buffer, PCBNEW_KICAD_MOD ); + fputs( buffer.c_str(), outfile ); fclose( outfile ); m_mruPath = fn.GetPath(); } -void BM2CMP_FRAME::ExportFile( FILE* aOutfile, OUTPUT_FMT_ID aFormat ) +void BM2CMP_FRAME::ExportToBuffer( std::string& aOutput, OUTPUT_FMT_ID aFormat ) { // Create a potrace bitmap int h = m_NB_Image.GetHeight(); @@ -710,7 +758,8 @@ void BM2CMP_FRAME::ExportFile( FILE* aOutfile, OUTPUT_FMT_ID aFormat ) if( aFormat == PCBNEW_KICAD_MOD ) modLayer = (BMP2CMP_MOD_LAYER) m_radio_PCBLayer->GetSelection(); - bitmap2component( potrace_bitmap, aOutfile, aFormat, m_imageDPI.x, m_imageDPI.y, modLayer ); + BITMAPCONV_INFO converter( aOutput ); + converter.ConvertBitmap( potrace_bitmap, aFormat, m_imageDPI.x, m_imageDPI.y, modLayer ); } @@ -785,6 +834,7 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ) return start_common( aCtlBits ); } + void BM2CMP_FRAME::OnFormatChange( wxCommandEvent& event ) { if( m_radioBoxFormat->GetSelection() == PCBNEW_KICAD_MOD ) diff --git a/bitmap2component/bitmap2cmp_gui_base.cpp b/bitmap2component/bitmap2cmp_gui_base.cpp index 0d724d490a..c1caa410e4 100644 --- a/bitmap2component/bitmap2cmp_gui_base.cpp +++ b/bitmap2component/bitmap2cmp_gui_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Jan 17 2019) +// C++ code generated with wxFormBuilder (version Dec 1 2018) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -121,10 +121,11 @@ BM2CMP_FRAME_BASE::BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id, const wxS m_buttonLoad = new wxButton( m_panelRight, wxID_ANY, _("Load Bitmap"), wxDefaultPosition, wxDefaultSize, 0 ); brightSizer->Add( m_buttonLoad, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - m_buttonExport = new wxButton( m_panelRight, wxID_ANY, _("Export"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonExport->SetToolTip( _("Create a library file for Eeschema\nThis library contains only one component: logo") ); + m_buttonExportFile = new wxButton( m_panelRight, wxID_ANY, _("Export to File"), wxDefaultPosition, wxDefaultSize, 0 ); + brightSizer->Add( m_buttonExportFile, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - brightSizer->Add( m_buttonExport, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + m_buttonExportClipboard = new wxButton( m_panelRight, wxID_ANY, _("Export to Clipboard"), wxDefaultPosition, wxDefaultSize, 0 ); + brightSizer->Add( m_buttonExportClipboard, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); wxString m_radioBoxFormatChoices[] = { _("Eeschema (.lib file)"), _("Pcbnew (.kicad_mod file)"), _("Postscript (.ps file)"), _("Logo for title block (.kicad_wks file)") }; int m_radioBoxFormatNChoices = sizeof( m_radioBoxFormatChoices ) / sizeof( wxString ); @@ -137,7 +138,7 @@ BM2CMP_FRAME_BASE::BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id, const wxS m_ThresholdText = new wxStaticText( sbSizer2->GetStaticBox(), wxID_ANY, _("Black / White Threshold:"), wxDefaultPosition, wxDefaultSize, 0 ); m_ThresholdText->Wrap( -1 ); - sbSizer2->Add( m_ThresholdText, 0, 0, 5 ); + sbSizer2->Add( m_ThresholdText, 0, wxTOP|wxLEFT, 5 ); m_sliderThreshold = new wxSlider( sbSizer2->GetStaticBox(), wxID_ANY, 50, 0, 100, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL|wxSL_LABELS ); m_sliderThreshold->SetToolTip( _("Adjust the level to convert the greyscale picture to a black and white picture.") ); @@ -145,7 +146,7 @@ BM2CMP_FRAME_BASE::BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id, const wxS sbSizer2->Add( m_sliderThreshold, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); m_checkNegative = new wxCheckBox( sbSizer2->GetStaticBox(), wxID_ANY, _("Negative"), wxDefaultPosition, wxDefaultSize, 0 ); - sbSizer2->Add( m_checkNegative, 0, wxBOTTOM|wxTOP, 10 ); + sbSizer2->Add( m_checkNegative, 0, wxTOP|wxBOTTOM, 10 ); brightSizer->Add( sbSizer2, 0, wxALL|wxEXPAND, 5 ); @@ -178,7 +179,8 @@ BM2CMP_FRAME_BASE::BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id, const wxS m_DPIValueY->Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( BM2CMP_FRAME_BASE::UpdatePPITextValueY ), NULL, this ); m_DPIValueY->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnResolutionChange ), NULL, this ); m_buttonLoad->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnLoadFile ), NULL, this ); - m_buttonExport->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnExport ), NULL, this ); + m_buttonExportFile->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnExportToFile ), NULL, this ); + m_buttonExportClipboard->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnExportToClipboard ), NULL, this ); m_radioBoxFormat->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnFormatChange ), NULL, this ); m_sliderThreshold->Connect( wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler( BM2CMP_FRAME_BASE::OnThresholdChange ), NULL, this ); m_checkNegative->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnNegativeClicked ), NULL, this ); @@ -195,7 +197,8 @@ BM2CMP_FRAME_BASE::~BM2CMP_FRAME_BASE() m_DPIValueY->Disconnect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( BM2CMP_FRAME_BASE::UpdatePPITextValueY ), NULL, this ); m_DPIValueY->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnResolutionChange ), NULL, this ); m_buttonLoad->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnLoadFile ), NULL, this ); - m_buttonExport->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnExport ), NULL, this ); + m_buttonExportFile->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnExportToFile ), NULL, this ); + m_buttonExportClipboard->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnExportToClipboard ), NULL, this ); m_radioBoxFormat->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnFormatChange ), NULL, this ); m_sliderThreshold->Disconnect( wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler( BM2CMP_FRAME_BASE::OnThresholdChange ), NULL, this ); m_checkNegative->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnNegativeClicked ), NULL, this ); diff --git a/bitmap2component/bitmap2cmp_gui_base.fbp b/bitmap2component/bitmap2cmp_gui_base.fbp index ba627ab720..c4f4240548 100644 --- a/bitmap2component/bitmap2cmp_gui_base.fbp +++ b/bitmap2component/bitmap2cmp_gui_base.fbp @@ -45,7 +45,7 @@ BM2CMP_FRAME_BASE - 733,634 + 733,616 wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER KIWAY_PLAYER; kiway_player.h Bitmap to Component Converter @@ -1435,7 +1435,7 @@ 0 0 wxID_ANY - Export + Export to File 0 @@ -1445,7 +1445,7 @@ 0 1 - m_buttonExport + m_buttonExportFile 1 @@ -1460,7 +1460,7 @@ 0 - Create a library file for Eeschema This library contains only one component: logo + wxFILTER_NONE wxDefaultValidator @@ -1468,7 +1468,80 @@ - OnExport + OnExportToFile + + + + 5 + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + Export to Clipboard + + 0 + + 0 + + + 0 + + 1 + m_buttonExportClipboard + 1 + + + protected + 1 + + + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnExportToClipboard @@ -1552,7 +1625,7 @@ none 5 - + wxTOP|wxLEFT 0 1 @@ -1679,7 +1752,7 @@ 10 - wxBOTTOM|wxTOP + wxTOP|wxBOTTOM 0 1 diff --git a/bitmap2component/bitmap2cmp_gui_base.h b/bitmap2component/bitmap2cmp_gui_base.h index a0500cbc15..0daf581b18 100644 --- a/bitmap2component/bitmap2cmp_gui_base.h +++ b/bitmap2component/bitmap2cmp_gui_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Jan 17 2019) +// C++ code generated with wxFormBuilder (version Dec 1 2018) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -65,7 +65,8 @@ class BM2CMP_FRAME_BASE : public KIWAY_PLAYER wxTextCtrl* m_DPIValueY; wxStaticText* m_DPI_Units; wxButton* m_buttonLoad; - wxButton* m_buttonExport; + wxButton* m_buttonExportFile; + wxButton* m_buttonExportClipboard; wxRadioBox* m_radioBoxFormat; wxStaticText* m_ThresholdText; wxSlider* m_sliderThreshold; @@ -81,7 +82,8 @@ class BM2CMP_FRAME_BASE : public KIWAY_PLAYER virtual void OnResolutionChange( wxCommandEvent& event ) { event.Skip(); } virtual void UpdatePPITextValueY( wxMouseEvent& event ) { event.Skip(); } virtual void OnLoadFile( wxCommandEvent& event ) { event.Skip(); } - virtual void OnExport( wxCommandEvent& event ) { event.Skip(); } + virtual void OnExportToFile( wxCommandEvent& event ) { event.Skip(); } + virtual void OnExportToClipboard( wxCommandEvent& event ) { event.Skip(); } virtual void OnFormatChange( wxCommandEvent& event ) { event.Skip(); } virtual void OnThresholdChange( wxScrollEvent& event ) { event.Skip(); } virtual void OnNegativeClicked( wxCommandEvent& event ) { event.Skip(); } @@ -89,7 +91,7 @@ class BM2CMP_FRAME_BASE : public KIWAY_PLAYER public: - BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Bitmap to Component Converter"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 733,634 ), long style = wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxTAB_TRAVERSAL ); + BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Bitmap to Component Converter"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 733,616 ), long style = wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxTAB_TRAVERSAL ); ~BM2CMP_FRAME_BASE(); diff --git a/bitmap2component/bitmap2component.cpp b/bitmap2component/bitmap2component.cpp index a0f6418206..cfdb4d15d1 100644 --- a/bitmap2component/bitmap2component.cpp +++ b/bitmap2component/bitmap2component.cpp @@ -24,6 +24,7 @@ #include // std::max #include +#include #include #include #include @@ -31,7 +32,6 @@ #include #include -#include #include #include @@ -53,61 +53,6 @@ static void bm_free( potrace_bitmap_t* bm ) } -/* Helper class to handle useful info to convert a bitmap image to - * a polygonal object description - */ -class BITMAPCONV_INFO -{ -public: - enum OUTPUT_FMT_ID m_Format; // File format - int m_PixmapWidth; - int m_PixmapHeight; // the bitmap size in pixels - double m_ScaleX; - double m_ScaleY; // the conversion scale - potrace_path_t* m_Paths; // the list of paths, from potrace (list of lines and bezier curves) - FILE* m_Outfile; // File to create - const char * m_CmpName; // The string used as cmp/footprint name - -public: - BITMAPCONV_INFO(); - - /** - * Function CreateOutputFile - * Creates the output file specified by m_Outfile, - * depending on file format given by m_Format - */ - void CreateOutputFile( BMP2CMP_MOD_LAYER aModLayer = (BMP2CMP_MOD_LAYER) 0 ); - - -private: - /** - * Function OuputFileHeader - * write to file the header depending on file format - */ - void OuputFileHeader( const char * aBrdLayerName ); - - /** - * Function OuputFileEnd - * write to file the last strings depending on file format - */ - void OuputFileEnd(); - - - /** - * @return the board layer name depending on the board layer selected - * @param aChoice = the choice (MOD_LYR_FSILKS to MOD_LYR_FINAL) - */ - const char * getBrdLayerName( BMP2CMP_MOD_LAYER aChoice ); - - /** - * Function OuputOnePolygon - * write one polygon to output file. - * Polygon coordinates are expected scaled by the polygon extraction function - */ - void OuputOnePolygon( SHAPE_LINE_CHAIN & aPolygon, const char* aBrdLayerName ); - -}; - static void BezierToPolyline( std::vector & aCornersBuffer, potrace_dpoint_t p1, potrace_dpoint_t p2, @@ -115,7 +60,8 @@ static void BezierToPolyline( std::vector & aCornersBuffer, potrace_dpoint_t p4 ); -BITMAPCONV_INFO::BITMAPCONV_INFO() +BITMAPCONV_INFO::BITMAPCONV_INFO( std::string& aData ): + m_Data( aData ) { m_Format = POSTSCRIPT_FMT; m_PixmapWidth = 0; @@ -123,12 +69,11 @@ BITMAPCONV_INFO::BITMAPCONV_INFO() m_ScaleX = 1.0; m_ScaleY = 1.0; m_Paths = NULL; - m_Outfile = NULL; m_CmpName = "LOGO"; } -int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile, +int BITMAPCONV_INFO::ConvertBitmap( potrace_bitmap_t* aPotrace_bitmap, OUTPUT_FMT_ID aFormat, int aDpi_X, int aDpi_Y, BMP2CMP_MOD_LAYER aModLayer ) { @@ -158,42 +103,39 @@ int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile, return 1; } - printf("Step 1\n"); - BITMAPCONV_INFO info; - info.m_PixmapWidth = aPotrace_bitmap->w; - info.m_PixmapHeight = aPotrace_bitmap->h; // the bitmap size in pixels - info.m_Paths = st->plist; - info.m_Outfile = aOutfile; + m_PixmapWidth = aPotrace_bitmap->w; + m_PixmapHeight = aPotrace_bitmap->h; // the bitmap size in pixels + m_Paths = st->plist; switch( aFormat ) { case KICAD_LOGO: - info.m_Format = KICAD_LOGO; - info.m_ScaleX = MM2MICRON * 25.4 / aDpi_X; // the conversion scale from PPI to micron - info.m_ScaleY = MM2MICRON * 25.4 / aDpi_Y; // Y axis is top to bottom - info.CreateOutputFile(); + m_Format = KICAD_LOGO; + m_ScaleX = MM2MICRON * 25.4 / aDpi_X; // the conversion scale from PPI to micron + m_ScaleY = MM2MICRON * 25.4 / aDpi_Y; // Y axis is top to bottom + createOutputData(); break; case POSTSCRIPT_FMT: - info.m_Format = POSTSCRIPT_FMT; - info.m_ScaleX = 1.0; // the conversion scale - info.m_ScaleY = info.m_ScaleX; + m_Format = POSTSCRIPT_FMT; + m_ScaleX = 1.0; // the conversion scale + m_ScaleY = m_ScaleX; // output vector data, e.g. as a rudimentary EPS file (mainly for tests) - info.CreateOutputFile(); + createOutputData(); break; case EESCHEMA_FMT: - info.m_Format = EESCHEMA_FMT; - info.m_ScaleX = 1000.0 / aDpi_X; // the conversion scale from PPI to UI (mil) - info.m_ScaleY = -1000.0 / aDpi_Y; // Y axis is bottom to Top for components in libs - info.CreateOutputFile(); + m_Format = EESCHEMA_FMT; + m_ScaleX = 1000.0 / aDpi_X; // the conversion scale from PPI to UI (mil) + m_ScaleY = -1000.0 / aDpi_Y; // Y axis is bottom to Top for components in libs + createOutputData(); break; case PCBNEW_KICAD_MOD: - info.m_Format = PCBNEW_KICAD_MOD; - info.m_ScaleX = MM2NANOMETER * 25.4 / aDpi_X; // the conversion scale from PPI to UI - info.m_ScaleY = MM2NANOMETER * 25.4 / aDpi_Y; // Y axis is top to bottom in modedit - info.CreateOutputFile( aModLayer ); + m_Format = PCBNEW_KICAD_MOD; + m_ScaleX = MM2NANOMETER * 25.4 / aDpi_X; // the conversion scale from PPI to UI + m_ScaleY = MM2NANOMETER * 25.4 / aDpi_Y; // Y axis is top to bottom in modedit + createOutputData( aModLayer ); break; default: @@ -236,85 +178,95 @@ const char* BITMAPCONV_INFO::getBrdLayerName( BMP2CMP_MOD_LAYER aChoice ) } -void BITMAPCONV_INFO::OuputFileHeader( const char * aBrdLayerName ) +void BITMAPCONV_INFO::outputDataHeader( const char * aBrdLayerName ) { int Ypos = (int) ( m_PixmapHeight / 2 * m_ScaleY ); int fieldSize; // fields text size = 60 mils + char strbuf[1024]; switch( m_Format ) { case POSTSCRIPT_FMT: /* output vector data, e.g. as a rudimentary EPS file */ - fprintf( m_Outfile, "%%!PS-Adobe-3.0 EPSF-3.0\n" ); - fprintf( m_Outfile, "%%%%BoundingBox: 0 0 %d %d\n", - m_PixmapWidth, m_PixmapHeight ); - fprintf( m_Outfile, "gsave\n" ); + m_Data += "%%!PS-Adobe-3.0 EPSF-3.0\n"; + sprintf( strbuf, "%%%%BoundingBox: 0 0 %d %d\n", m_PixmapWidth, m_PixmapHeight ); + m_Data += strbuf; + m_Data += "gsave\n"; break; case PCBNEW_KICAD_MOD: // fields text size = 1.5 mm // fields text thickness = 1.5 / 5 = 0.3mm - fprintf( m_Outfile, "(module %s (layer F.Cu)\n (at 0 0)\n", - m_CmpName ); - fprintf( m_Outfile, " (fp_text reference \"G***\" (at 0 0) (layer %s) hide\n" + sprintf( strbuf, "(module %s (layer F.Cu)\n (at 0 0)\n", m_CmpName.c_str() ); + m_Data += strbuf; + sprintf( strbuf, " (fp_text reference \"G***\" (at 0 0) (layer %s) hide\n" " (effects (font (thickness 0.3)))\n )\n", aBrdLayerName ); - fprintf( m_Outfile, " (fp_text value \"%s\" (at 0.75 0) (layer %s) hide\n" - " (effects (font (thickness 0.3)))\n )\n", m_CmpName, aBrdLayerName ); + m_Data += strbuf; + sprintf( strbuf, " (fp_text value \"%s\" (at 0.75 0) (layer %s) hide\n" + " (effects (font (thickness 0.3)))\n )\n", m_CmpName.c_str(), aBrdLayerName ); + m_Data += strbuf; break; case KICAD_LOGO: - fprintf( m_Outfile, "(polygon (pos 0 0 rbcorner) (rotate 0) (linewidth 0.01)\n" ); + m_Data += "(polygon (pos 0 0 rbcorner) (rotate 0) (linewidth 0.01)\n"; break; case EESCHEMA_FMT: - fprintf( m_Outfile, "EESchema-LIBRARY Version 2.3\n" ); - fprintf( m_Outfile, "#\n# %s\n", m_CmpName ); - fprintf( m_Outfile, "# pixmap size w = %d, h = %d\n#\n", + sprintf( strbuf, "EESchema-LIBRARY Version 2.3\n" ); + m_Data += strbuf; + sprintf( strbuf, "#\n# %s\n", m_CmpName.c_str() ); + m_Data += strbuf; + sprintf( strbuf, "# pixmap size w = %d, h = %d\n#\n", m_PixmapWidth, m_PixmapHeight ); + m_Data += strbuf; // print reference and value - fieldSize = 60; // fields text size = 60 mils + fieldSize = 50; // fields text size = 50 mils Ypos += fieldSize / 2; - fprintf( m_Outfile, "DEF %s G 0 40 Y Y 1 F N\n", m_CmpName ); - fprintf( m_Outfile, "F0 \"#G\" 0 %d %d H I C CNN\n", Ypos, fieldSize ); - fprintf( m_Outfile, "F1 \"%s\" 0 %d %d H I C CNN\n", m_CmpName, -Ypos, fieldSize ); - fprintf( m_Outfile, "DRAW\n" ); + sprintf( strbuf, "DEF %s G 0 40 Y Y 1 F N\n", m_CmpName.c_str() ); + m_Data += strbuf; + sprintf( strbuf, "F0 \"#G\" 0 %d %d H I C CNN\n", Ypos, fieldSize ); + m_Data += strbuf; + sprintf( strbuf, "F1 \"%s\" 0 %d %d H I C CNN\n", m_CmpName.c_str(), -Ypos, fieldSize ); + m_Data += strbuf; + m_Data += "DRAW\n"; break; } } -void BITMAPCONV_INFO::OuputFileEnd() +void BITMAPCONV_INFO::outputDataEnd() { switch( m_Format ) { case POSTSCRIPT_FMT: - fprintf( m_Outfile, "grestore\n" ); - fprintf( m_Outfile, "%%EOF\n" ); + m_Data += "grestore\n"; + m_Data += "%%EOF\n"; break; case PCBNEW_KICAD_MOD: - fprintf( m_Outfile, ")\n" ); + m_Data += ")\n"; break; case KICAD_LOGO: - fprintf( m_Outfile, ")\n" ); + m_Data += ")\n"; break; case EESCHEMA_FMT: - fprintf( m_Outfile, "ENDDRAW\n" ); - fprintf( m_Outfile, "ENDDEF\n" ); + m_Data += "ENDDRAW\n"; + m_Data += "ENDDEF\n"; break; } } -void BITMAPCONV_INFO::OuputOnePolygon( SHAPE_LINE_CHAIN & aPolygon, const char* aBrdLayerName ) +void BITMAPCONV_INFO::ouputOnePolygon( SHAPE_LINE_CHAIN & aPolygon, const char* aBrdLayerName ) { // write one polygon to output file. // coordinates are expected in target unit. int ii, jj; VECTOR2I currpoint; + char strbuf[1024]; int offsetX = (int)( m_PixmapWidth / 2 * m_ScaleX ); int offsetY = (int)( m_PixmapHeight / 2 * m_ScaleY ); @@ -325,94 +277,102 @@ void BITMAPCONV_INFO::OuputOnePolygon( SHAPE_LINE_CHAIN & aPolygon, const char* { case POSTSCRIPT_FMT: offsetY = (int)( m_PixmapHeight * m_ScaleY ); - fprintf( m_Outfile, "newpath\n%d %d moveto\n", + sprintf( strbuf, "newpath\n%d %d moveto\n", startpoint.x, offsetY - startpoint.y ); + m_Data += strbuf; jj = 0; for( ii = 1; ii < aPolygon.PointCount(); ii++ ) { currpoint = aPolygon.CPoint( ii ); - fprintf( m_Outfile, " %d %d lineto", + sprintf( strbuf, " %d %d lineto", currpoint.x, offsetY - currpoint.y ); + m_Data += strbuf; if( jj++ > 6 ) { jj = 0; - fprintf( m_Outfile, ("\n") ); + m_Data += "\n"; } } - fprintf( m_Outfile, "\nclosepath fill\n" ); + m_Data += "\nclosepath fill\n"; break; case PCBNEW_KICAD_MOD: { double width = 0.01; // outline thickness in mm - fprintf( m_Outfile, " (fp_poly (pts" ); + m_Data += " (fp_poly (pts"; jj = 0; for( ii = 0; ii < aPolygon.PointCount(); ii++ ) { currpoint = aPolygon.CPoint( ii ); - fprintf( m_Outfile, " (xy %f %f)", + sprintf( strbuf, " (xy %f %f)", ( currpoint.x - offsetX ) / MM2NANOMETER, ( currpoint.y - offsetY ) / MM2NANOMETER ); + m_Data += strbuf; if( jj++ > 6 ) { jj = 0; - fprintf( m_Outfile, ("\n ") ); + m_Data += "\n "; } } // No need to close polygon - fprintf( m_Outfile, " )" ); - fprintf( m_Outfile, "(layer %s) (width %f)\n )\n", aBrdLayerName, width ); - + m_Data += " )"; + sprintf( strbuf, "(layer %s) (width %f)\n )\n", aBrdLayerName, width ); + m_Data += strbuf; } break; case KICAD_LOGO: - fprintf( m_Outfile, " (pts" ); + m_Data += " (pts"; // Internal units = micron, file unit = mm jj = 0; for( ii = 0; ii < aPolygon.PointCount(); ii++ ) { currpoint = aPolygon.CPoint( ii ); - fprintf( m_Outfile, " (xy %.3f %.3f)", + sprintf( strbuf, " (xy %.3f %.3f)", ( currpoint.x - offsetX ) / MM2MICRON, ( currpoint.y - offsetY ) / MM2MICRON ); + m_Data += strbuf; if( jj++ > 4 ) { jj = 0; - fprintf( m_Outfile, ("\n ") ); + m_Data += "\n "; } } // Close polygon - fprintf( m_Outfile, " (xy %.3f %.3f) )\n", + sprintf( strbuf, " (xy %.3f %.3f) )\n", ( startpoint.x - offsetX ) / MM2MICRON, ( startpoint.y - offsetY ) / MM2MICRON ); + m_Data += strbuf; break; case EESCHEMA_FMT: - fprintf( m_Outfile, "P %d 0 0 1", (int) aPolygon.PointCount() + 1 ); + sprintf( strbuf, "P %d 0 0 1", (int) aPolygon.PointCount() + 1 ); + m_Data += strbuf; for( ii = 0; ii < aPolygon.PointCount(); ii++ ) { currpoint = aPolygon.CPoint( ii ); - fprintf( m_Outfile, " %d %d", + sprintf( strbuf, " %d %d", currpoint.x - offsetX, currpoint.y - offsetY ); + m_Data += strbuf; } // Close polygon - fprintf( m_Outfile, " %d %d", + sprintf( strbuf, " %d %d", startpoint.x - offsetX, startpoint.y - offsetY ); + m_Data += strbuf; - fprintf( m_Outfile, " F\n" ); + m_Data += " F\n"; break; } } -void BITMAPCONV_INFO::CreateOutputFile( BMP2CMP_MOD_LAYER aModLayer ) +void BITMAPCONV_INFO::createOutputData( BMP2CMP_MOD_LAYER aModLayer ) { std::vector cornersBuffer; @@ -429,7 +389,7 @@ void BITMAPCONV_INFO::CreateOutputFile( BMP2CMP_MOD_LAYER aModLayer ) // The layer name has meaning only for .kicad_mod files. // For these files the header creates 2 invisible texts: value and ref // (needed but not usefull) on silk screen layer - OuputFileHeader( getBrdLayerName( MOD_LYR_FSILKS ) ); + outputDataHeader( getBrdLayerName( MOD_LYR_FSILKS ) ); bool main_outline = true; @@ -437,8 +397,10 @@ void BITMAPCONV_INFO::CreateOutputFile( BMP2CMP_MOD_LAYER aModLayer ) * Bezier curves are approximated by a polyline */ potrace_path_t* paths = m_Paths; // the list of paths + if(!m_Paths) printf("NULL Paths!\n"); + while( paths != NULL ) { int cnt = paths->curve.n; @@ -506,7 +468,7 @@ void BITMAPCONV_INFO::CreateOutputFile( BMP2CMP_MOD_LAYER aModLayer ) for( int ii = 0; ii < polyset_areas.OutlineCount(); ii++ ) { SHAPE_LINE_CHAIN& poly = polyset_areas.Outline( ii ); - OuputOnePolygon(poly, getBrdLayerName( aModLayer ) ); + ouputOnePolygon(poly, getBrdLayerName( aModLayer ) ); } polyset_areas.RemoveAllContours(); @@ -516,7 +478,7 @@ void BITMAPCONV_INFO::CreateOutputFile( BMP2CMP_MOD_LAYER aModLayer ) paths = paths->next; } - OuputFileEnd(); + outputDataEnd(); } // a helper function to calculate a square value diff --git a/bitmap2component/bitmap2component.h b/bitmap2component/bitmap2component.h index 602a713891..ac47902e03 100644 --- a/bitmap2component/bitmap2component.h +++ b/bitmap2component/bitmap2component.h @@ -24,6 +24,8 @@ #ifndef BITMAP2COMPONENT_H #define BITMAP2COMPONENT_H +#include + // for consistency this enum should conform to the // indices in m_radioBoxFormat from bitmap2cmp_gui.cpp enum OUTPUT_FMT_ID @@ -44,4 +46,65 @@ enum BMP2CMP_MOD_LAYER MOD_LYR_FINAL = MOD_LYR_ECO2 }; + +/* Helper class to handle useful info to convert a bitmap image to + * a polygonal object description + */ +class BITMAPCONV_INFO +{ +private: + enum OUTPUT_FMT_ID m_Format; // File format + int m_PixmapWidth; + int m_PixmapHeight; // the bitmap size in pixels + double m_ScaleX; + double m_ScaleY; // the conversion scale + potrace_path_t* m_Paths; // the list of paths, from potrace (list of lines and bezier curves) + std::string m_CmpName; // The string used as cmp/footprint name + std::string& m_Data; // the buffer containing the conversion + +public: + BITMAPCONV_INFO( std::string& aData ); + + /** + * Run the conversion of the bitmap + */ + int ConvertBitmap( potrace_bitmap_t* aPotrace_bitmap, + OUTPUT_FMT_ID aFormat, int aDpi_X, int aDpi_Y, + BMP2CMP_MOD_LAYER aModLayer ); + + +private: + /** + * Creates the data specified by m_Format + */ + void createOutputData( BMP2CMP_MOD_LAYER aModLayer = (BMP2CMP_MOD_LAYER) 0 ); + + /** + * Function outputDataHeader + * write to file the header depending on file format + */ + void outputDataHeader( const char * aBrdLayerName ); + + /** + * Function outputDataEnd + * write to file the last strings depending on file format + */ + void outputDataEnd(); + + + /** + * @return the board layer name depending on the board layer selected + * @param aChoice = the choice (MOD_LYR_FSILKS to MOD_LYR_FINAL) + */ + const char * getBrdLayerName( BMP2CMP_MOD_LAYER aChoice ); + + /** + * Function ouputOnePolygon + * write one polygon to output file. + * Polygon coordinates are expected scaled by the polygon extraction function + */ + void ouputOnePolygon( SHAPE_LINE_CHAIN & aPolygon, const char* aBrdLayerName ); + +}; + #endif // BITMAP2COMPONENT_H