← Back to team overview

kicad-developers team mailing list archive

Fixing libcommon

 

In order to remove the hardcoded values from WORKSHEET_VIEWITEM, I
started moving code that used to be compiled multiple times to separate
units. This is also a basic way to solve the internal units conversion
problem.

There are still a few more files that are compiled multiple times. I
plan to fix them as well, but first I want to send the first patches to
see if we all agree on the proposed solution.

Alternatively, there could be an abstract class to provide conversion
methods. If it is preferred, then we need to decide how to access its
instance (singleton, attach to KiFace, static object?)

Ultimately we can have a real common library for all apps (libkicommon?)
that could be compiled as a shared library. Such approach should reduce
*.kiface files size and linking time.

Any thoughts?

Regards,
Orson
>From 36c8dc6bc565ed6a9a9532624bc506c19df8fab3 Mon Sep 17 00:00:00 2001
From: Maciej Suminski <maciej.suminski@xxxxxxx>
Date: Sat, 18 Mar 2017 11:25:37 +0100
Subject: [PATCH 1/4] Move IU_PER_{MILS,MM} constants to separate iu.cpp files

---
 common/base_units.cpp            | 10 ------
 cvpcb/CMakeLists.txt             |  1 +
 cvpcb/iu.cpp                     | 27 +++++++++++++++
 eeschema/CMakeLists.txt          |  1 +
 eeschema/iu.cpp                  | 27 +++++++++++++++
 gerbview/CMakeLists.txt          |  1 +
 gerbview/iu.cpp                  | 27 +++++++++++++++
 include/convert_to_biu.h         | 71 +++++++++++-----------------------------
 pagelayout_editor/CMakeLists.txt |  1 +
 pagelayout_editor/iu.cpp         | 27 +++++++++++++++
 pcbnew/CMakeLists.txt            |  1 +
 pcbnew/iu.cpp                    | 27 +++++++++++++++
 12 files changed, 160 insertions(+), 61 deletions(-)
 create mode 100644 cvpcb/iu.cpp
 create mode 100644 eeschema/iu.cpp
 create mode 100644 gerbview/iu.cpp
 create mode 100644 pagelayout_editor/iu.cpp
 create mode 100644 pcbnew/iu.cpp

diff --git a/common/base_units.cpp b/common/base_units.cpp
index bd03bcf3a..06e5847e5 100644
--- a/common/base_units.cpp
+++ b/common/base_units.cpp
@@ -41,16 +41,6 @@
 #include <base_units.h>
 
 
-#if defined( PCBNEW ) || defined( CVPCB ) || defined( EESCHEMA ) || defined( GERBVIEW ) || defined( PL_EDITOR )
-#define IU_TO_MM( x )       ( x / IU_PER_MM )
-#define IU_TO_IN( x )       ( x / IU_PER_MILS / 1000 )
-#define MM_TO_IU( x )       ( x * IU_PER_MM )
-#define IN_TO_IU( x )       ( x * IU_PER_MILS * 1000 )
-#else
-#error "Cannot resolve internal units due to no definition of EESCHEMA, CVPCB or PCBNEW."
-#endif
-
-
 // Helper function to print a float number without using scientific notation
 // and no trailing 0
 // So we cannot always just use the %g or the %f format to print a fp number
diff --git a/cvpcb/CMakeLists.txt b/cvpcb/CMakeLists.txt
index 0c7508a5f..5706f1db3 100644
--- a/cvpcb/CMakeLists.txt
+++ b/cvpcb/CMakeLists.txt
@@ -44,6 +44,7 @@ set( CVPCB_SRCS
     class_footprints_listbox.cpp
     class_library_listbox.cpp
     cvpcb_mainframe.cpp
+    iu.cpp
     listboxes.cpp
     menubar.cpp
     readwrite_dlgs.cpp
diff --git a/cvpcb/iu.cpp b/cvpcb/iu.cpp
new file mode 100644
index 000000000..5c205c97e
--- /dev/null
+++ b/cvpcb/iu.cpp
@@ -0,0 +1,27 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
+ */
+
+// Internal units constants for cvpcb
+
+extern constexpr double IU_PER_MM   = 1e6;
+extern constexpr double IU_PER_MILS = IU_PER_MM * 0.0254;
diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt
index 1e1908267..b23e61327 100644
--- a/eeschema/CMakeLists.txt
+++ b/eeschema/CMakeLists.txt
@@ -113,6 +113,7 @@ set( EESCHEMA_SRCS
     hierarch.cpp
     highlight_connection.cpp
     hotkeys.cpp
+    iu.cpp
     libarch.cpp
     libedit.cpp
     libeditframe.cpp
diff --git a/eeschema/iu.cpp b/eeschema/iu.cpp
new file mode 100644
index 000000000..ae45b0215
--- /dev/null
+++ b/eeschema/iu.cpp
@@ -0,0 +1,27 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
+ */
+
+// Internal units constants for eeschema
+
+extern constexpr double IU_PER_MILS = 1.0;
+extern constexpr double IU_PER_MM   = IU_PER_MILS / 0.0254;
diff --git a/gerbview/CMakeLists.txt b/gerbview/CMakeLists.txt
index c63272a1f..ee38c7c47 100644
--- a/gerbview/CMakeLists.txt
+++ b/gerbview/CMakeLists.txt
@@ -50,6 +50,7 @@ set( GERBVIEW_SRCS
     gerbview_config.cpp
     gerbview_frame.cpp
     hotkeys.cpp
+    iu.cpp
     clear_gbr_drawlayers.cpp
     locate.cpp
     menubar.cpp
diff --git a/gerbview/iu.cpp b/gerbview/iu.cpp
new file mode 100644
index 000000000..db56c749a
--- /dev/null
+++ b/gerbview/iu.cpp
@@ -0,0 +1,27 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
+ */
+
+// Internal units constants for gerbview
+
+extern constexpr double IU_PER_MM   = 1e5;
+extern constexpr double IU_PER_MILS = IU_PER_MM * 0.0254;
diff --git a/include/convert_to_biu.h b/include/convert_to_biu.h
index 795f79d48..3dde47f24 100644
--- a/include/convert_to_biu.h
+++ b/include/convert_to_biu.h
@@ -2,7 +2,7 @@
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
  * Copyright (C) 2012-2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
- * Copyright (C) 1992-2016 KiCad Developers, see CHANGELOG.TXT for contributors.
+ * Copyright (C) 1992-2017 KiCad Developers, see CHANGELOG.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
@@ -26,78 +26,47 @@
 #define CONVERT_TO_BIU_H_
 
 /**
- * @file convert_to_biu.h
+ * @brief Constants and functions to convert a value in mils, decimils or mm to the internal units.
  */
 
-/**
- * @brief some define and functions to convert a value in mils, decimils or mm
- * to the internal unit used in pcbnew, cvpcb or gerbview (nanometer or deci-mil)
- * depending on compile time option
- */
+/// Scaling factor to convert millimeters to internal units.
+extern const double IU_PER_MM;
 
 /// Scaling factor to convert mils to internal units.
-#if defined(PCBNEW) || defined(CVPCB) || defined(GERBVIEW)
- #if defined(GERBVIEW)
-  constexpr double IU_PER_MM = 1e5;     // Gerbview IU is 10 nanometers.
- #else
-  constexpr double IU_PER_MM = 1e6;     // Pcbnew IU is 1 nanometer.
- #endif
+extern const double IU_PER_MILS;
 
-constexpr double IU_PER_MILS = IU_PER_MM * 0.0254;
+/// Scaling factor to convert internal units to millimeters.
+const double MM_PER_IU = ( 1 / IU_PER_MM );
 
-/// Convert mils to PCBNEW internal units (iu).
+/// Convert mils to PCBNEW internal units (iu)
 inline int Mils2iu( int mils )
 {
     double x = mils * IU_PER_MILS;
     return int( x < 0 ? x - 0.5 : x + 0.5 );
 }
 
-#elif defined (PL_EDITOR)
-constexpr double IU_PER_MM   =   1e3; // internal units in micron (should be enough)
-constexpr double IU_PER_MILS = (IU_PER_MM * 0.0254);
-
-/// Convert mils to page layout editor internal units (iu).
-inline int Mils2iu( int mils )
-{
-    double x = mils * IU_PER_MILS;
-    return int( x < 0 ? x - 0.5 : x + 0.5 );
-}
-
-#elif defined (EESCHEMA)            // Eeschema
-constexpr double IU_PER_MILS = 1.0;
-constexpr double IU_PER_MM   = ( IU_PER_MILS / 0.0254 );
-
-constexpr inline int Mils2iu( int mils )
-{
-    return mils;
-}
-#else
-// Here, we do not know the value of internal units: do not define
-// conversion functions (They do not have meaning)
-#define UNKNOWN_IU
-#endif
-
-#ifndef UNKNOWN_IU
-// Other definitions used in a few files
-constexpr double MM_PER_IU = ( 1 / IU_PER_MM );
-
-/// Convert mm to internal units (iu).
-constexpr inline int Millimeter2iu( double mm )
+/// Convert mm to internal units (iu)
+inline int Millimeter2iu( double mm )
 {
     return (int) ( mm < 0 ? mm * IU_PER_MM - 0.5 : mm * IU_PER_MM + 0.5 );
 }
 
-/// Convert mm to internal units (iu).
-constexpr inline double Iu2Millimeter( int iu )
+/// Convert internal units to millimeters
+inline double Iu2Millimeter( int iu )
 {
     return iu / IU_PER_MM;
 }
 
-/// Convert mm to internal units (iu).
-constexpr inline double Iu2Mils( int iu )
+/// Convert internal units (iu) to mils
+inline double Iu2Mils( int iu )
 {
     return iu / IU_PER_MILS;
 }
-#endif
+
+// Macros used in the code
+#define IU_TO_MM( x )       ( x / IU_PER_MM )
+#define IU_TO_IN( x )       ( x / IU_PER_MILS / 1000 )
+#define MM_TO_IU( x )       ( x * IU_PER_MM )
+#define IN_TO_IU( x )       ( x * IU_PER_MILS * 1000 )
 
 #endif  // CONVERT_TO_BIU_H_
diff --git a/pagelayout_editor/CMakeLists.txt b/pagelayout_editor/CMakeLists.txt
index 74ae57571..84ea308ce 100644
--- a/pagelayout_editor/CMakeLists.txt
+++ b/pagelayout_editor/CMakeLists.txt
@@ -23,6 +23,7 @@ set( PL_EDITOR_SRCS
     events_functions.cpp
     controle.cpp
     files.cpp
+    iu.cpp
     onleftclick.cpp
     onrightclick.cpp
     page_layout_writer.cpp
diff --git a/pagelayout_editor/iu.cpp b/pagelayout_editor/iu.cpp
new file mode 100644
index 000000000..1466a1231
--- /dev/null
+++ b/pagelayout_editor/iu.cpp
@@ -0,0 +1,27 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
+ */
+
+// Internal units constants for pl_editor
+
+extern constexpr double IU_PER_MM   = 1e3;
+extern constexpr double IU_PER_MILS = IU_PER_MM * 0.0254;
diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt
index 806574181..8c7d638e7 100644
--- a/pcbnew/CMakeLists.txt
+++ b/pcbnew/CMakeLists.txt
@@ -240,6 +240,7 @@ set( PCBNEW_CLASS_SRCS
     hotkeys_board_editor.cpp
     hotkeys_module_editor.cpp
     initpcb.cpp
+    iu.cpp
     layer_widget.cpp
     librairi.cpp
     loadcmp.cpp
diff --git a/pcbnew/iu.cpp b/pcbnew/iu.cpp
new file mode 100644
index 000000000..a7ffedf57
--- /dev/null
+++ b/pcbnew/iu.cpp
@@ -0,0 +1,27 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
+ */
+
+// Internal units constants for pcbnew
+
+extern constexpr double IU_PER_MM   = 1e6;
+extern constexpr double IU_PER_MILS = IU_PER_MM * 0.0254;
-- 
2.11.1

>From 2d7230c68d9c9fb6a3c9070c307a836ca0069476 Mon Sep 17 00:00:00 2001
From: Maciej Suminski <maciej.suminski@xxxxxxx>
Date: Sat, 18 Mar 2017 13:55:58 +0100
Subject: [PATCH 2/4] Unify FMT_IU and FMTIU to a single form in
 kicad_plugin.cpp

---
 pcbnew/kicad_plugin.cpp | 76 ++++++++++++++++++++++++-------------------------
 1 file changed, 37 insertions(+), 39 deletions(-)

diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp
index eedff9ec3..aaa246213 100644
--- a/pcbnew/kicad_plugin.cpp
+++ b/pcbnew/kicad_plugin.cpp
@@ -52,8 +52,6 @@
 
 using namespace PCB_KEYS_T;
 
-#define FMTIU        BOARD_ITEM::FormatInternalUnits
-
 /**
  * Definition for enabling and disabling footprint library trace output.  See the
  * wxWidgets documentation on using the WXTRACE environment variable.
@@ -525,10 +523,10 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const
     // Write Bounding box info
     EDA_RECT bbox = aBoard->GetBoundingBox();
     m_out->Print( aNestLevel+1,  "(area %s %s %s %s)\n",
-                  FMTIU( bbox.GetX() ).c_str(), FMTIU( bbox.GetY() ).c_str(),
-                  FMTIU( bbox.GetRight() ).c_str(), FMTIU( bbox.GetBottom() ).c_str() );
+                  FMT_IU( bbox.GetX() ).c_str(), FMT_IU( bbox.GetY() ).c_str(),
+                  FMT_IU( bbox.GetRight() ).c_str(), FMT_IU( bbox.GetBottom() ).c_str() );
     m_out->Print( aNestLevel+1, "(thickness %s)\n",
-                  FMTIU( dsnSettings.GetBoardThickness() ).c_str() );
+                  FMT_IU( dsnSettings.GetBoardThickness() ).c_str() );
 
     m_out->Print( aNestLevel+1, "(drawings %d)\n", aBoard->m_Drawings.GetCount() );
     m_out->Print( aNestLevel+1, "(tracks %d)\n", aBoard->GetNumSegmTrack() );
@@ -603,105 +601,105 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const
 
     // Save current default track width, for compatibility with older Pcbnew version;
     m_out->Print( aNestLevel+1, "(last_trace_width %s)\n",
-                  FMTIU( dsnSettings.GetCurrentTrackWidth() ).c_str() );
+                  FMT_IU( dsnSettings.GetCurrentTrackWidth() ).c_str() );
 
     // Save custom tracks width list (the first is not saved here: this is the netclass value
     for( unsigned ii = 1; ii < dsnSettings.m_TrackWidthList.size(); ii++ )
         m_out->Print( aNestLevel+1, "(user_trace_width %s)\n",
-                      FMTIU( dsnSettings.m_TrackWidthList[ii] ).c_str() );
+                      FMT_IU( dsnSettings.m_TrackWidthList[ii] ).c_str() );
 
     m_out->Print( aNestLevel+1, "(trace_clearance %s)\n",
-                  FMTIU( dsnSettings.GetDefault()->GetClearance() ).c_str() );
+                  FMT_IU( dsnSettings.GetDefault()->GetClearance() ).c_str() );
 
     // ZONE_SETTINGS
     m_out->Print( aNestLevel+1, "(zone_clearance %s)\n",
-                  FMTIU( aBoard->GetZoneSettings().m_ZoneClearance ).c_str() );
+                  FMT_IU( aBoard->GetZoneSettings().m_ZoneClearance ).c_str() );
     m_out->Print( aNestLevel+1, "(zone_45_only %s)\n",
                   aBoard->GetZoneSettings().m_Zone_45_Only ? "yes" : "no" );
 
     m_out->Print( aNestLevel+1, "(trace_min %s)\n",
-                  FMTIU( dsnSettings.m_TrackMinWidth ).c_str() );
+                  FMT_IU( dsnSettings.m_TrackMinWidth ).c_str() );
 
     m_out->Print( aNestLevel+1, "(segment_width %s)\n",
-                  FMTIU( dsnSettings.m_DrawSegmentWidth ).c_str() );
+                  FMT_IU( dsnSettings.m_DrawSegmentWidth ).c_str() );
     m_out->Print( aNestLevel+1, "(edge_width %s)\n",
-                  FMTIU( dsnSettings.m_EdgeSegmentWidth ).c_str() );
+                  FMT_IU( dsnSettings.m_EdgeSegmentWidth ).c_str() );
 
     // Save current default via size, for compatibility with older Pcbnew version;
     m_out->Print( aNestLevel+1, "(via_size %s)\n",
-                  FMTIU( dsnSettings.GetDefault()->GetViaDiameter() ).c_str() );
+                  FMT_IU( dsnSettings.GetDefault()->GetViaDiameter() ).c_str() );
     m_out->Print( aNestLevel+1, "(via_drill %s)\n",
-                  FMTIU( dsnSettings.GetDefault()->GetViaDrill() ).c_str() );
+                  FMT_IU( dsnSettings.GetDefault()->GetViaDrill() ).c_str() );
     m_out->Print( aNestLevel+1, "(via_min_size %s)\n",
-                  FMTIU( dsnSettings.m_ViasMinSize ).c_str() );
+                  FMT_IU( dsnSettings.m_ViasMinSize ).c_str() );
     m_out->Print( aNestLevel+1, "(via_min_drill %s)\n",
-                  FMTIU( dsnSettings.m_ViasMinDrill ).c_str() );
+                  FMT_IU( dsnSettings.m_ViasMinDrill ).c_str() );
 
     // Save custom vias diameters list (the first is not saved here: this is
     // the netclass value
     for( unsigned ii = 1; ii < dsnSettings.m_ViasDimensionsList.size(); ii++ )
         m_out->Print( aNestLevel+1, "(user_via %s %s)\n",
-                      FMTIU( dsnSettings.m_ViasDimensionsList[ii].m_Diameter ).c_str(),
-                      FMTIU( dsnSettings.m_ViasDimensionsList[ii].m_Drill ).c_str() );
+                      FMT_IU( dsnSettings.m_ViasDimensionsList[ii].m_Diameter ).c_str(),
+                      FMT_IU( dsnSettings.m_ViasDimensionsList[ii].m_Drill ).c_str() );
 
     // for old versions compatibility:
     if( dsnSettings.m_BlindBuriedViaAllowed )
         m_out->Print( aNestLevel+1, "(blind_buried_vias_allowed yes)\n" );
 
     m_out->Print( aNestLevel+1, "(uvia_size %s)\n",
-                  FMTIU( dsnSettings.GetDefault()->GetuViaDiameter() ).c_str() );
+                  FMT_IU( dsnSettings.GetDefault()->GetuViaDiameter() ).c_str() );
     m_out->Print( aNestLevel+1, "(uvia_drill %s)\n",
-                  FMTIU( dsnSettings.GetDefault()->GetuViaDrill() ).c_str() );
+                  FMT_IU( dsnSettings.GetDefault()->GetuViaDrill() ).c_str() );
     m_out->Print( aNestLevel+1, "(uvias_allowed %s)\n",
                   ( dsnSettings.m_MicroViasAllowed ) ? "yes" : "no" );
     m_out->Print( aNestLevel+1, "(uvia_min_size %s)\n",
-                  FMTIU( dsnSettings.m_MicroViasMinSize ).c_str() );
+                  FMT_IU( dsnSettings.m_MicroViasMinSize ).c_str() );
     m_out->Print( aNestLevel+1, "(uvia_min_drill %s)\n",
-                  FMTIU( dsnSettings.m_MicroViasMinDrill ).c_str() );
+                  FMT_IU( dsnSettings.m_MicroViasMinDrill ).c_str() );
 
     m_out->Print( aNestLevel+1, "(pcb_text_width %s)\n",
-                  FMTIU( dsnSettings.m_PcbTextWidth ).c_str() );
+                  FMT_IU( dsnSettings.m_PcbTextWidth ).c_str() );
     m_out->Print( aNestLevel+1, "(pcb_text_size %s %s)\n",
-                  FMTIU( dsnSettings.m_PcbTextSize.x ).c_str(),
-                  FMTIU( dsnSettings.m_PcbTextSize.y ).c_str() );
+                  FMT_IU( dsnSettings.m_PcbTextSize.x ).c_str(),
+                  FMT_IU( dsnSettings.m_PcbTextSize.y ).c_str() );
 
     m_out->Print( aNestLevel+1, "(mod_edge_width %s)\n",
-                  FMTIU( dsnSettings.m_ModuleSegmentWidth ).c_str() );
+                  FMT_IU( dsnSettings.m_ModuleSegmentWidth ).c_str() );
     m_out->Print( aNestLevel+1, "(mod_text_size %s %s)\n",
-                  FMTIU( dsnSettings.m_ModuleTextSize.x ).c_str(),
-                  FMTIU( dsnSettings.m_ModuleTextSize.y ).c_str() );
+                  FMT_IU( dsnSettings.m_ModuleTextSize.x ).c_str(),
+                  FMT_IU( dsnSettings.m_ModuleTextSize.y ).c_str() );
     m_out->Print( aNestLevel+1, "(mod_text_width %s)\n",
-                  FMTIU( dsnSettings.m_ModuleTextWidth ).c_str() );
+                  FMT_IU( dsnSettings.m_ModuleTextWidth ).c_str() );
 
     m_out->Print( aNestLevel+1, "(pad_size %s %s)\n",
-                  FMTIU( dsnSettings.m_Pad_Master.GetSize().x ).c_str(),
-                  FMTIU( dsnSettings.m_Pad_Master.GetSize().y ).c_str() );
+                  FMT_IU( dsnSettings.m_Pad_Master.GetSize().x ).c_str(),
+                  FMT_IU( dsnSettings.m_Pad_Master.GetSize().y ).c_str() );
     m_out->Print( aNestLevel+1, "(pad_drill %s)\n",
-                  FMTIU( dsnSettings.m_Pad_Master.GetDrillSize().x ).c_str() );
+                  FMT_IU( dsnSettings.m_Pad_Master.GetDrillSize().x ).c_str() );
 
     m_out->Print( aNestLevel+1, "(pad_to_mask_clearance %s)\n",
-                  FMTIU( dsnSettings.m_SolderMaskMargin ).c_str() );
+                  FMT_IU( dsnSettings.m_SolderMaskMargin ).c_str() );
 
     if( dsnSettings.m_SolderMaskMinWidth )
         m_out->Print( aNestLevel+1, "(solder_mask_min_width %s)\n",
-                      FMTIU( dsnSettings.m_SolderMaskMinWidth ).c_str() );
+                      FMT_IU( dsnSettings.m_SolderMaskMinWidth ).c_str() );
 
     if( dsnSettings.m_SolderPasteMargin != 0 )
         m_out->Print( aNestLevel+1, "(pad_to_paste_clearance %s)\n",
-                      FMTIU( dsnSettings.m_SolderPasteMargin ).c_str() );
+                      FMT_IU( dsnSettings.m_SolderPasteMargin ).c_str() );
 
     if( dsnSettings.m_SolderPasteMarginRatio != 0 )
         m_out->Print( aNestLevel+1, "(pad_to_paste_clearance_ratio %s)\n",
                       Double2Str( dsnSettings.m_SolderPasteMarginRatio ).c_str() );
 
     m_out->Print( aNestLevel+1, "(aux_axis_origin %s %s)\n",
-                  FMTIU( aBoard->GetAuxOrigin().x ).c_str(),
-                  FMTIU( aBoard->GetAuxOrigin().y ).c_str() );
+                  FMT_IU( aBoard->GetAuxOrigin().x ).c_str(),
+                  FMT_IU( aBoard->GetAuxOrigin().y ).c_str() );
 
     if( aBoard->GetGridOrigin().x || aBoard->GetGridOrigin().y )
         m_out->Print( aNestLevel+1, "(grid_origin %s %s)\n",
-                      FMTIU( aBoard->GetGridOrigin().x ).c_str(),
-                      FMTIU( aBoard->GetGridOrigin().y ).c_str() );
+                      FMT_IU( aBoard->GetGridOrigin().x ).c_str(),
+                      FMT_IU( aBoard->GetGridOrigin().y ).c_str() );
 
     m_out->Print( aNestLevel+1, "(visible_elements %X)\n",
                   dsnSettings.GetVisibleElements() );
-- 
2.11.1

>From 09f06c8018cc46c9e3b2d5dd73f1bcaa0539b005 Mon Sep 17 00:00:00 2001
From: Maciej Suminski <maciej.suminski@xxxxxxx>
Date: Sat, 18 Mar 2017 14:55:33 +0100
Subject: [PATCH 3/4] eda_text.cpp made common for all apps

- Moved {SCH,BOARD}_ITEM::FormatInternalUnits(double) to corresponding
iu.cpp files. Other apps use Double2Str().
- Other FormatInternalUnits() variants moved to convert_to_biu.cpp, as they
were identical in every application.
- FormatAngle() moved to convert_to_biu.cpp as the code was identical
in every application.
---
 common/CMakeLists.txt            |   3 +-
 common/convert_to_biu.cpp        |  46 +++++++++++++++++
 common/eda_text.cpp              |  15 ------
 cvpcb/iu.cpp                     |   8 +++
 eeschema/CMakeLists.txt          |   1 -
 eeschema/iu.cpp                  |  27 ++++++++++
 eeschema/sch_item_struct.cpp     |  47 ------------------
 eeschema/sch_item_struct.h       |  29 -----------
 gerbview/CMakeLists.txt          |   1 -
 gerbview/iu.cpp                  |   8 +++
 include/class_board_item.h       |  31 ------------
 include/convert_to_biu.h         |  27 ++++++++++
 pagelayout_editor/CMakeLists.txt |   1 -
 pagelayout_editor/iu.cpp         |   8 +++
 pcbnew/class_board.cpp           |  16 +++---
 pcbnew/class_board_item.cpp      | 103 ---------------------------------------
 pcbnew/iu.cpp                    |  30 ++++++++++++
 pcbnew/specctra_export.cpp       |   8 +--
 18 files changed, 168 insertions(+), 241 deletions(-)
 create mode 100644 common/convert_to_biu.cpp

diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 29e25daee..0d434302a 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -226,6 +226,7 @@ set( COMMON_SRCS
     common_plotSVG_functions.cpp
     config_params.cpp
     confirm.cpp
+    convert_to_biu.cpp
     copy_to_clipboard.cpp
     convert_basic_shapes_to_polygon.cpp
     dialog_shim.cpp
@@ -237,6 +238,7 @@ set( COMMON_SRCS
     eda_dde.cpp
     eda_doc.cpp
     eda_pattern_match.cpp
+    eda_text.cpp
     exceptions.cpp
     filter_reader.cpp
     lib_id.cpp
@@ -344,7 +346,6 @@ target_link_libraries( common
 
 set( PCB_COMMON_SRCS
     base_screen.cpp
-    eda_text.cpp
     class_page_info.cpp
     lset.cpp
     footprint_info.cpp
diff --git a/common/convert_to_biu.cpp b/common/convert_to_biu.cpp
new file mode 100644
index 000000000..bbe6806db
--- /dev/null
+++ b/common/convert_to_biu.cpp
@@ -0,0 +1,46 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 KiCad Developers, see CHANGELOG.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 <convert_to_biu.h>
+#include <wx/gdicmn.h>
+
+std::string FMT_IU( const wxPoint& aPoint )
+{
+    return FMT_IU( aPoint.x ) + " " + FMT_IU( aPoint.y );
+}
+
+
+std::string FMT_IU( const wxSize& aSize )
+{
+    return FMT_IU( aSize.GetWidth() ) + " " + FMT_IU( aSize.GetHeight() );
+}
+
+
+std::string FMT_ANGLE( double aAngle )
+{
+    char temp[50];
+
+    int len = snprintf( temp, sizeof(temp), "%.10g", aAngle / 10.0 );
+
+    return std::string( temp, len );
+}
diff --git a/common/eda_text.cpp b/common/eda_text.cpp
index 8c57c606d..880b25eac 100644
--- a/common/eda_text.cpp
+++ b/common/eda_text.cpp
@@ -33,22 +33,7 @@
 #include <macros.h>
 #include <trigo.h>               // RotatePoint
 #include <class_drawpanel.h>     // EDA_DRAW_PANEL
-
 #include <basic_gal.h>
-
-// Conversion to application internal units defined at build time.
-#if defined( PCBNEW )
-    #include <class_board_item.h>       // for FMT_IU
-#elif defined( EESCHEMA )
-    #include <sch_item_struct.h>        // for FMT_IU
-#elif defined( GERBVIEW )
-#elif defined( PL_EDITOR )
-    #include <base_units.h>
-    #define FMT_IU Double2Str
-#else
-#error "Cannot resolve units formatting due to no definition of EESCHEMA or PCBNEW."
-#endif
-
 #include <convert_to_biu.h>
 
 EDA_TEXT::EDA_TEXT( const wxString& text ) :
diff --git a/cvpcb/iu.cpp b/cvpcb/iu.cpp
index 5c205c97e..6d60459ff 100644
--- a/cvpcb/iu.cpp
+++ b/cvpcb/iu.cpp
@@ -21,7 +21,15 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
+#include <base_units.h>
+
 // Internal units constants for cvpcb
 
 extern constexpr double IU_PER_MM   = 1e6;
 extern constexpr double IU_PER_MILS = IU_PER_MM * 0.0254;
+
+
+std::string FMT_IU( double aValue )
+{
+    return Double2Str( aValue );
+}
diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt
index b23e61327..ace8154ec 100644
--- a/eeschema/CMakeLists.txt
+++ b/eeschema/CMakeLists.txt
@@ -201,7 +201,6 @@ set( EESCHEMA_SRCS
 set( EESCHEMA_COMMON_SRCS
     ../common/dialogs/dialog_page_settings.cpp
     ../common/base_screen.cpp
-    ../common/eda_text.cpp
     ../common/class_page_info.cpp
     ../common/base_units.cpp
     )
diff --git a/eeschema/iu.cpp b/eeschema/iu.cpp
index ae45b0215..2199ecdfd 100644
--- a/eeschema/iu.cpp
+++ b/eeschema/iu.cpp
@@ -21,7 +21,34 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
+#include <string>
+#include <cmath>
+
 // Internal units constants for eeschema
 
 extern constexpr double IU_PER_MILS = 1.0;
 extern constexpr double IU_PER_MM   = IU_PER_MILS / 0.0254;
+
+
+std::string FMT_IU( double aValue )
+{
+    char    buf[50];
+    double  engUnits = aValue;
+    int     len;
+
+    if( engUnits != 0.0 && std::fabs( engUnits ) <= 0.0001 )
+    {
+        len = snprintf( buf, sizeof(buf), "%.10f", engUnits );
+
+        while( --len > 0 && buf[len] == '0' )
+            buf[len] = '\0';
+
+        ++len;
+    }
+    else
+    {
+        len = snprintf( buf, sizeof(buf), "%.10g", engUnits );
+    }
+
+    return std::string( buf, len );
+}
diff --git a/eeschema/sch_item_struct.cpp b/eeschema/sch_item_struct.cpp
index 047d5c869..52ec375e9 100644
--- a/eeschema/sch_item_struct.cpp
+++ b/eeschema/sch_item_struct.cpp
@@ -102,50 +102,3 @@ void SCH_ITEM::Plot( PLOTTER* aPlotter )
 {
     wxFAIL_MSG( wxT( "Plot() method not implemented for class " ) + GetClass() );
 }
-
-
-std::string SCH_ITEM::FormatInternalUnits( int aValue )
-{
-    char    buf[50];
-    double  engUnits = aValue;
-    int     len;
-
-    if( engUnits != 0.0 && fabs( engUnits ) <= 0.0001 )
-    {
-        len = snprintf( buf, sizeof(buf), "%.10f", engUnits );
-
-        while( --len > 0 && buf[len] == '0' )
-            buf[len] = '\0';
-
-        ++len;
-    }
-    else
-    {
-        len = snprintf( buf, sizeof(buf), "%.10g", engUnits );
-    }
-
-    return std::string( buf, len );
-}
-
-
-std::string SCH_ITEM::FormatAngle( double aAngle )
-{
-    char temp[50];
-    int len;
-
-    len = snprintf( temp, sizeof(temp), "%.10g", aAngle / 10.0 );
-
-    return std::string( temp, len );
-}
-
-
-std::string SCH_ITEM::FormatInternalUnits( const wxPoint& aPoint )
-{
-    return FormatInternalUnits( aPoint.x ) + " " + FormatInternalUnits( aPoint.y );
-}
-
-
-std::string SCH_ITEM::FormatInternalUnits( const wxSize& aSize )
-{
-    return FormatInternalUnits( aSize.GetWidth() ) + " " + FormatInternalUnits( aSize.GetHeight() );
-}
diff --git a/eeschema/sch_item_struct.h b/eeschema/sch_item_struct.h
index 7f5dc1f7b..34a80b27e 100644
--- a/eeschema/sch_item_struct.h
+++ b/eeschema/sch_item_struct.h
@@ -51,10 +51,6 @@ typedef SCH_ITEMS::iterator SCH_ITEMS_ITR;
 typedef std::vector< SCH_ITEMS_ITR > SCH_ITEMS_ITRS;
 
 
-#define FMT_IU          SCH_ITEM::FormatInternalUnits
-#define FMT_ANGLE       SCH_ITEM::FormatAngle
-
-
 /// Flag to enable find item tracing using the WXTRACE environment variable.  This
 /// flag generates a lot of debug output.
 extern const wxString traceFindItem;
@@ -382,31 +378,6 @@ public:
 
     virtual bool operator <( const SCH_ITEM& aItem ) const;
 
-    /**
-     * Function FormatInternalUnits
-     * converts \a aValue from schematic internal units to a string appropriate for writing
-     * to file.
-     *
-     * @param aValue A coordinate value to convert.
-     * @return A std::string object containing the converted value.
-     */
-    static std::string FormatInternalUnits( int aValue );
-
-    /**
-     * Function FormatAngle
-     * converts \a aAngle from board units to a string appropriate for writing to file.
-     *
-     * @note Internal angles for board items can be either degrees or tenths of degree
-     *       on how KiCad is built.
-     * @param aAngle A angle value to convert.
-     * @return A std::string object containing the converted angle.
-     */
-    static std::string FormatAngle( double aAngle );
-
-    static std::string FormatInternalUnits( const wxPoint& aPoint );
-
-    static std::string FormatInternalUnits( const wxSize& aSize );
-
 private:
     /**
      * Function doIsConnected
diff --git a/gerbview/CMakeLists.txt b/gerbview/CMakeLists.txt
index ee38c7c47..2adf4fd41 100644
--- a/gerbview/CMakeLists.txt
+++ b/gerbview/CMakeLists.txt
@@ -68,7 +68,6 @@ set( GERBVIEW_SRCS
 set( GERBVIEW_EXTRA_SRCS
     ../common/base_screen.cpp
     ../common/base_units.cpp
-    ../common/eda_text.cpp
     ../common/class_layer_box_selector.cpp
     ../common/class_page_info.cpp
     ../pcbnew/layer_widget.cpp
diff --git a/gerbview/iu.cpp b/gerbview/iu.cpp
index db56c749a..b1bee30b1 100644
--- a/gerbview/iu.cpp
+++ b/gerbview/iu.cpp
@@ -21,7 +21,15 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
+#include <base_units.h>
+
 // Internal units constants for gerbview
 
 extern constexpr double IU_PER_MM   = 1e5;
 extern constexpr double IU_PER_MILS = IU_PER_MM * 0.0254;
+
+
+std::string FMT_IU( double aValue )
+{
+    return Double2Str( aValue );
+}
diff --git a/include/class_board_item.h b/include/class_board_item.h
index 34c275c14..74ab2f6b9 100644
--- a/include/class_board_item.h
+++ b/include/class_board_item.h
@@ -35,10 +35,6 @@
 #include <gr_basic.h>
 #include <layers_id_colors_and_visibility.h>
 
-/// Abbrevation for fomatting internal units to a string.
-#define FMT_IU     BOARD_ITEM::FormatInternalUnits
-#define FMT_ANGLE  BOARD_ITEM::FormatAngle
-
 class BOARD;
 class BOARD_ITEM_CONTAINER;
 class EDA_DRAW_PANEL;
@@ -299,33 +295,6 @@ public:
         return false;   // derived classes should override this function
     }
 
-
-    /**
-     * Function FormatInternalUnits
-     * converts \a aValue from board internal units to a string appropriate for writing to file.
-     *
-     * @note Internal units for board items can be either deci-mils or nanometers depending
-     *       on how KiCad is build.
-     * @param aValue A coordinate value to convert.
-     * @return A std::string object containing the converted value.
-     */
-    static std::string FormatInternalUnits( int aValue );
-
-    /**
-     * Function FormatAngle
-     * converts \a aAngle from board units to a string appropriate for writing to file.
-     *
-     * @note Internal angles for board items can be either degrees or tenths of degree
-     *       on how KiCad is built.
-     * @param aAngle A angle value to convert.
-     * @return A std::string object containing the converted angle.
-     */
-    static std::string FormatAngle( double aAngle );
-
-    static std::string FormatInternalUnits( const wxPoint& aPoint );
-
-    static std::string FormatInternalUnits( const wxSize& aSize );
-
     /// @copydoc VIEW_ITEM::ViewGetLayers()
     virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;
 };
diff --git a/include/convert_to_biu.h b/include/convert_to_biu.h
index 3dde47f24..9b72a8676 100644
--- a/include/convert_to_biu.h
+++ b/include/convert_to_biu.h
@@ -25,6 +25,11 @@
 #ifndef CONVERT_TO_BIU_H_
 #define CONVERT_TO_BIU_H_
 
+#include <string>
+
+class wxPoint;
+class wxSize;
+
 /**
  * @brief Constants and functions to convert a value in mils, decimils or mm to the internal units.
  */
@@ -63,6 +68,28 @@ inline double Iu2Mils( int iu )
     return iu / IU_PER_MILS;
 }
 
+/**
+ * Function FMT_ANGLE
+ * converts \a aAngle from board units to a string appropriate for writing to file.
+ *
+ * @param aAngle An angle value to convert.
+ * @return A std::string object containing the converted angle.
+ */
+std::string FMT_ANGLE( double aAngle );
+
+/**
+ * Function FMT_IU
+ * converts \a aValue from schematic internal units to a string appropriate for writing to file.
+ *
+ * @param aValue A coordinate value to convert.
+ * @return A std::string object containing the converted value.
+ */
+extern std::string FMT_IU( double aValue );
+
+std::string FMT_IU( const wxPoint& aPoint );
+
+std::string FMT_IU( const wxSize& aSize );
+
 // Macros used in the code
 #define IU_TO_MM( x )       ( x / IU_PER_MM )
 #define IU_TO_IN( x )       ( x / IU_PER_MILS / 1000 )
diff --git a/pagelayout_editor/CMakeLists.txt b/pagelayout_editor/CMakeLists.txt
index 84ea308ce..35d8b2ac3 100644
--- a/pagelayout_editor/CMakeLists.txt
+++ b/pagelayout_editor/CMakeLists.txt
@@ -40,7 +40,6 @@ set( PL_EDITOR_SRCS
 set( PL_EDITOR_EXTRA_SRCS
     ../common/base_screen.cpp
     ../common/base_units.cpp
-    ../common/eda_text.cpp
     ../common/class_page_info.cpp
     ../common/dialogs/dialog_page_settings.cpp
 )
diff --git a/pagelayout_editor/iu.cpp b/pagelayout_editor/iu.cpp
index 1466a1231..86600e312 100644
--- a/pagelayout_editor/iu.cpp
+++ b/pagelayout_editor/iu.cpp
@@ -21,7 +21,15 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
+#include <base_units.h>
+
 // Internal units constants for pl_editor
 
 extern constexpr double IU_PER_MM   = 1e3;
 extern constexpr double IU_PER_MILS = IU_PER_MM * 0.0254;
+
+
+std::string FMT_IU( double aValue )
+{
+    return Double2Str( aValue );
+}
diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp
index f32c0bf99..914b65e64 100644
--- a/pcbnew/class_board.cpp
+++ b/pcbnew/class_board.cpp
@@ -303,9 +303,9 @@ static void checkConnectedTo( BOARD* aBoard, TRACKS* aList, const TRACKS& aTrack
         {
             std::string m = StrPrintf(
                 "intervening pad at:(xy %s) between start:(xy %s) and goal:(xy %s)",
-                BOARD_ITEM::FormatInternalUnits( next ).c_str(),
-                BOARD_ITEM::FormatInternalUnits( aStart ).c_str(),
-                BOARD_ITEM::FormatInternalUnits( aGoal ).c_str()
+                FMT_IU( next ).c_str(),
+                FMT_IU( aStart ).c_str(),
+                FMT_IU( aGoal ).c_str()
                 );
             THROW_IO_ERROR( m );
         }
@@ -317,7 +317,7 @@ static void checkConnectedTo( BOARD* aBoard, TRACKS* aList, const TRACKS& aTrack
             std::string m = StrPrintf(
                 "found %d tracks intersecting at (xy %s), exactly 2 would be acceptable.",
                 track_count + aList->size() == 1 ? 1 : 0,
-                BOARD_ITEM::FormatInternalUnits( next ).c_str()
+                FMT_IU( next ).c_str()
                 );
             THROW_IO_ERROR( m );
         }
@@ -330,8 +330,8 @@ static void checkConnectedTo( BOARD* aBoard, TRACKS* aList, const TRACKS& aTrack
 
     std::string m = StrPrintf(
         "not enough tracks connecting start:(xy %s) and goal:(xy %s).",
-        BOARD_ITEM::FormatInternalUnits( aStart ).c_str(),
-        BOARD_ITEM::FormatInternalUnits( aGoal ).c_str()
+        FMT_IU( aStart ).c_str(),
+        FMT_IU( aGoal ).c_str()
         );
     THROW_IO_ERROR( m );
 }
@@ -375,8 +375,8 @@ TRACKS BOARD::TracksInNetBetweenPoints( const wxPoint& aStartPos, const wxPoint&
 
     wxString m = wxString::Format(
             "no clean path connecting start:(xy %s) with goal:(xy %s)",
-            BOARD_ITEM::FormatInternalUnits( aStartPos ).c_str(),
-            BOARD_ITEM::FormatInternalUnits( aGoalPos ).c_str()
+            FMT_IU( aStartPos ).c_str(),
+            FMT_IU( aGoalPos ).c_str()
             );
 
     THROW_IO_ERROR( m + per_path_problem_text );
diff --git a/pcbnew/class_board_item.cpp b/pcbnew/class_board_item.cpp
index 6cacf21f5..cd3114c98 100644
--- a/pcbnew/class_board_item.cpp
+++ b/pcbnew/class_board_item.cpp
@@ -86,109 +86,6 @@ wxString BOARD_ITEM::GetLayerName() const
 }
 
 
-std::string BOARD_ITEM::FormatInternalUnits( int aValue )
-{
-#if 1
-
-    char    buf[50];
-    int     len;
-    double  mm = aValue / IU_PER_MM;
-
-    if( mm != 0.0 && fabs( mm ) <= 0.0001 )
-    {
-        len = sprintf( buf, "%.10f", mm );
-
-        while( --len > 0 && buf[len] == '0' )
-            buf[len] = '\0';
-
-        if( buf[len] == '.' )
-            buf[len] = '\0';
-        else
-            ++len;
-    }
-    else
-    {
-        len = sprintf( buf, "%.10g", mm );
-    }
-
-    return std::string( buf, len );
-
-#else
-
-    // Assume aValue is in nanometers, and that we want the result in millimeters,
-    // and that int is 32 bits wide.  Then perform an alternative algorithm.
-    // Can be used to verify that the above algorithm is correctly generating text.
-    // Convert aValue into an integer string, then insert a decimal point manually.
-    // Results are the same as above general purpose algorithm.
-
-    wxASSERT( sizeof(int) == 4 );
-
-    if( aValue == 0 )
-        return std::string( 1, '0' );
-    else
-    {
-        char    buf[50];
-        int     len = sprintf( buf, aValue > 0 ? "%06d" : "%07d", aValue );     // optionally pad w/leading zeros
-
-        std::string ret( buf, len );
-
-        std::string::iterator it = ret.end() - 1;           // last byte
-
-        // insert '.' at 6 positions from end, dividing by 10e6 (a million), nm => mm
-        std::string::iterator decpoint = ret.end() - 6;
-
-        // truncate trailing zeros, up to decimal point position
-        for(  ; *it=='0' && it >= decpoint;  --it )
-            ret.erase( it );    // does not invalidate iterators it or decpoint
-
-        if( it >= decpoint )
-        {
-            ret.insert( decpoint, '.' );
-
-            // decpoint is invalidated here, after insert()
-
-#if 1       // want a leading zero when decimal point is in first position?
-            if( ret[0] == '.' )
-            {
-                // insert leading zero ahead of decimal point.
-                ret.insert( ret.begin(), '0' );
-            }
-            else if( ret[0]=='-' && ret[1]=='.' )
-            {
-                ret.insert( ret.begin() + 1, '0' );
-            }
-#endif
-        }
-
-        return ret;
-    }
-
-#endif
-}
-
-
-std::string BOARD_ITEM::FormatAngle( double aAngle )
-{
-    char temp[50];
-
-    int len = snprintf( temp, sizeof(temp), "%.10g", aAngle / 10.0 );
-
-    return std::string( temp, len );
-}
-
-
-std::string BOARD_ITEM::FormatInternalUnits( const wxPoint& aPoint )
-{
-    return FormatInternalUnits( aPoint.x ) + " " + FormatInternalUnits( aPoint.y );
-}
-
-
-std::string BOARD_ITEM::FormatInternalUnits( const wxSize& aSize )
-{
-    return FormatInternalUnits( aSize.GetWidth() ) + " " + FormatInternalUnits( aSize.GetHeight() );
-}
-
-
 void BOARD_ITEM::ViewGetLayers( int aLayers[], int& aCount ) const
 {
     // Basic fallback
diff --git a/pcbnew/iu.cpp b/pcbnew/iu.cpp
index a7ffedf57..741c4fb00 100644
--- a/pcbnew/iu.cpp
+++ b/pcbnew/iu.cpp
@@ -21,7 +21,37 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
+#include <string>
+#include <cmath>
+
 // Internal units constants for pcbnew
 
 extern constexpr double IU_PER_MM   = 1e6;
 extern constexpr double IU_PER_MILS = IU_PER_MM * 0.0254;
+
+
+std::string FMT_IU( double aValue )
+{
+    char    buf[50];
+    int     len;
+    double  mm = aValue / IU_PER_MM;
+
+    if( mm != 0.0 && fabs( mm ) <= 0.0001 )
+    {
+        len = sprintf( buf, "%.10f", mm );
+
+        while( --len > 0 && buf[len] == '0' )
+            buf[len] = '\0';
+
+        if( buf[len] == '.' )
+            buf[len] = '\0';
+        else
+            ++len;
+    }
+    else
+    {
+        len = sprintf( buf, "%.10g", mm );
+    }
+
+    return std::string( buf, len );
+}
diff --git a/pcbnew/specctra_export.cpp b/pcbnew/specctra_export.cpp
index 3e8e99fbb..b7a6da4c4 100644
--- a/pcbnew/specctra_export.cpp
+++ b/pcbnew/specctra_export.cpp
@@ -1159,8 +1159,8 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary )
                         wxString error = wxString::Format(
                             _( "Unable to find the next boundary segment with an endpoint of (%s mm, %s mm). "
                                 "Edge.Cuts perimeter graphics must form a contiguous, closed polygon." ),
-                            GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.x ).c_str() ) ),
-                            GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.y ).c_str() ) )
+                            GetChars( FROM_UTF8( FMT_IU( prevPt.x ).c_str() ) ),
+                            GetChars( FROM_UTF8( FMT_IU( prevPt.y ).c_str() ) )
                         );
                         THROW_IO_ERROR( error );
                     }
@@ -1294,8 +1294,8 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary )
                             wxString error = wxString::Format(
                                 _( "Unable to find the next keepout segment with an endpoint of (%s mm, %s mm).\n"
                                    "Edit Edge.Cuts interior graphics, making them contiguous polygons each." ),
-                                GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.x ).c_str() ) ),
-                                GetChars( FROM_UTF8( BOARD_ITEM::FormatInternalUnits( prevPt.y ).c_str() ) )
+                                GetChars( FROM_UTF8( FMT_IU( prevPt.x ).c_str() ) ),
+                                GetChars( FROM_UTF8( FMT_IU( prevPt.y ).c_str() ) )
                             );
 
                             THROW_IO_ERROR( error );
-- 
2.11.1

>From 2e654bbfb5a2790a0663f0c2743ebdf119560850 Mon Sep 17 00:00:00 2001
From: Maciej Suminski <maciej.suminski@xxxxxxx>
Date: Sat, 18 Mar 2017 14:58:29 +0100
Subject: [PATCH 4/4] Remove hardcoded scaling values in WORKSHEET_VIEWITEM

---
 common/worksheet_viewitem.cpp | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/common/worksheet_viewitem.cpp b/common/worksheet_viewitem.cpp
index 18f8fb98e..f4d11f5f5 100644
--- a/common/worksheet_viewitem.cpp
+++ b/common/worksheet_viewitem.cpp
@@ -34,6 +34,7 @@
 #include <layers_id_colors_and_visibility.h>
 #include <class_page_info.h>
 #include <view/view.h>
+#include <convert_to_biu.h>
 
 using namespace KIGFX;
 
@@ -82,10 +83,7 @@ void WORKSHEET_VIEWITEM::ViewDraw( int aLayer, VIEW* aView ) const
     WS_DRAW_ITEM_LIST drawList;
 
     drawList.SetPenSize( settings->GetWorksheetLineWidth() );
-    // Sorry, but I don't get this multi #ifdef from include/convert_to_biu.h, so here goes a magic
-    // number. IU_PER_MILS should be 25400 (as in a different compilation unit), but somehow
-    // it equals 1 in this case..
-    drawList.SetMilsToIUfactor( 25400 /* IU_PER_MILS */ );
+    drawList.SetMilsToIUfactor( IU_PER_MILS );
     drawList.SetSheetNumber( m_sheetNumber );
     drawList.SetSheetCount( m_sheetCount );
     drawList.SetFileName( fileName );
@@ -199,8 +197,8 @@ void WORKSHEET_VIEWITEM::draw( const WS_DRAW_ITEM_TEXT* aItem, GAL* aGal ) const
 void WORKSHEET_VIEWITEM::drawBorder( GAL* aGal ) const
 {
     VECTOR2D origin = VECTOR2D( 0.0, 0.0 );
-    VECTOR2D end = VECTOR2D( m_pageInfo->GetWidthMils() * 25400,
-                             m_pageInfo->GetHeightMils() * 25400 );
+    VECTOR2D end = VECTOR2D( Mils2iu( m_pageInfo->GetWidthMils() ),
+                             Mils2iu( m_pageInfo->GetHeightMils() ) );
 
     aGal->SetIsStroke( true );
     // Use a gray color for the border color
-- 
2.11.1


Follow ups