From a8613ee80f9700f0c961c24082d125e9d951f987 Mon Sep 17 00:00:00 2001
From: Marek Roszko <mark.roszko@gmail.com>
Date: Fri, 16 Sep 2022 07:33:56 -0400
Subject: [PATCH] Combine Iu2Millimeter & remove PcbMm2iu

---
 3d-viewer/3d_canvas/board_adapter.cpp         |  14 +-
 .../3d_rendering/opengl/render_3d_opengl.cpp  |   8 +-
 common/netclass.cpp                           |  18 +-
 common/pg_properties.cpp                      |   2 +-
 common/project/net_settings.cpp               |   4 +-
 eeschema/dialogs/dialog_plot_schematic.cpp    |  10 +-
 eeschema/lib_pin.cpp                          |   6 +-
 eeschema/sch_marker.cpp                       |   2 +-
 eeschema/sch_painter.cpp                      |   2 +-
 .../cadstar/cadstar_sch_archive_loader.cpp    |   2 +-
 eeschema/symbol_editor/symbol_edit_frame.cpp  |   8 +-
 eeschema/symbol_viewer_frame.cpp              |   4 +-
 gerbview/dcode.cpp                            |   2 +-
 gerbview/gerber_draw_item.cpp                 |   4 +-
 gerbview/gerber_file_image.cpp                |   4 +-
 gerbview/gerbview_painter.cpp                 |   2 +-
 include/convert_to_biu.h                      |  22 +-
 .../dialogs/design_inspector.cpp              |   3 +-
 pagelayout_editor/pl_draw_panel_gal.cpp       |   2 +-
 pcbnew/autorouter/ar_autoplacer.cpp           |   6 +-
 pcbnew/autorouter/spread_footprints.cpp       |   2 +-
 pcbnew/board.cpp                              |   4 +-
 pcbnew/board_design_settings.cpp              | 268 +++++++++---------
 pcbnew/board_item.cpp                         |   2 +-
 .../board_stackup_manager/board_stackup.cpp   |   6 +-
 pcbnew/convert_shape_list_to_polygon.cpp      |   4 +-
 pcbnew/dialogs/dialog_copper_zones.cpp        |   8 +-
 pcbnew/dialogs/dialog_create_array.cpp        |   4 +-
 pcbnew/dialogs/dialog_export_step.cpp         |  12 +-
 pcbnew/dialogs/dialog_export_vrml.cpp         |   4 +-
 .../dialog_non_copper_zones_properties.cpp    |   8 +-
 .../dialog_pad_basicshapes_properties.cpp     |   2 +-
 pcbnew/dialogs/dialog_pad_properties.cpp      |   2 +-
 pcbnew/dialogs/dialog_plot.cpp                |   2 +-
 .../dialogs/dialog_rule_area_properties.cpp   |   4 +-
 .../drc/drc_test_provider_library_parity.cpp  |   2 +-
 pcbnew/drc/drc_test_provider_misc.cpp         |   2 +-
 .../drc/drc_test_provider_sliver_checker.cpp  |   2 +-
 pcbnew/exporters/export_idf.cpp               |   8 +-
 pcbnew/exporters/exporter_vrml.cpp            |  34 +--
 pcbnew/exporters/gen_drill_report_files.cpp   |  10 +-
 pcbnew/exporters/gerber_placefile_writer.cpp  |   6 +-
 pcbnew/footprint.cpp                          |  12 +-
 pcbnew/footprint_edit_frame.cpp               |   2 +-
 pcbnew/footprint_editor_settings.cpp          |  36 +--
 pcbnew/fp_text.cpp                            |   2 +-
 pcbnew/import_gfx/dialog_import_gfx.cpp       |  10 +-
 pcbnew/import_gfx/dxf_import_plugin.cpp       |   1 -
 .../import_gfx/graphics_importer_pcbnew.cpp   |   2 +-
 .../netlist_reader/board_netlist_updater.cpp  |   2 +-
 pcbnew/pad.cpp                                |   4 +-
 pcbnew/pcb_base_frame.cpp                     |   4 +-
 pcbnew/pcb_dimension.cpp                      |   2 +-
 pcbnew/pcb_group.cpp                          |   2 +-
 pcbnew/pcb_marker.cpp                         |   2 +-
 pcbnew/pcb_painter.cpp                        |   4 +-
 pcbnew/pcb_plot_params.cpp                    |   2 +-
 pcbnew/pcb_shape.cpp                          |   4 +-
 pcbnew/pcb_target.cpp                         |   4 +-
 pcbnew/pcb_track.cpp                          |   6 +-
 pcbnew/pcbnew_printout.cpp                    |   2 +-
 pcbnew/plot_board_layers.cpp                  |   6 +-
 pcbnew/plot_brditems_plotter.cpp              |   2 +-
 pcbnew/plugins/altium/altium_pcb.cpp          |   6 +-
 pcbnew/plugins/eagle/eagle_plugin.cpp         |   8 +-
 pcbnew/plugins/kicad/pcb_parser.cpp           |   4 +-
 pcbnew/plugins/pcad/pcad2kicad_common.cpp     |   2 +-
 pcbnew/plugins/pcad/pcb_pad.cpp               |   2 +-
 pcbnew/teardrop/teardrop.cpp                  |   8 +-
 pcbnew/teardrop/teardrop_parameters.h         |   4 +-
 pcbnew/teardrop/teardrop_utils.cpp            |   2 +-
 pcbnew/tools/drawing_stackup_table_tool.cpp   |  20 +-
 pcbnew/tools/drawing_tool.cpp                 |   4 +-
 pcbnew/tools/edit_tool.cpp                    |   2 +-
 pcbnew/tools/pcb_point_editor.cpp             |   2 +-
 pcbnew/tools/pcb_selection_tool.cpp           |   2 +-
 pcbnew/zone.cpp                               |   8 +-
 pcbnew/zone_filler.cpp                        |  14 +-
 qa/unittests/eeschema/test_sch_biu.cpp        |   4 +-
 .../libs/kimath/geometry/test_shape_arc.cpp   |  14 +-
 80 files changed, 364 insertions(+), 374 deletions(-)

diff --git a/3d-viewer/3d_canvas/board_adapter.cpp b/3d-viewer/3d_canvas/board_adapter.cpp
index 19cbbea0dc..19a4134e36 100644
--- a/3d-viewer/3d_canvas/board_adapter.cpp
+++ b/3d-viewer/3d_canvas/board_adapter.cpp
@@ -40,13 +40,13 @@
 #include <advanced_config.h>
 
 
-#define DEFAULT_BOARD_THICKNESS Millimeter2iu( 1.6 )
-#define DEFAULT_COPPER_THICKNESS Millimeter2iu( 0.035 )   // for 35 um
+#define DEFAULT_BOARD_THICKNESS pcbIUScale.mmToIU( 1.6 )
+#define DEFAULT_COPPER_THICKNESS pcbIUScale.mmToIU( 0.035 ) // for 35 um
 // The solder mask layer (and silkscreen) thickness
-#define DEFAULT_TECH_LAYER_THICKNESS Millimeter2iu( 0.025 )
+#define DEFAULT_TECH_LAYER_THICKNESS pcbIUScale.mmToIU( 0.025 )
 // The solder paste thickness is chosen bigger than the solder mask layer
 // to be sure is covers the mask when overlapping.
-#define SOLDERPASTE_LAYER_THICKNESS Millimeter2iu( 0.04 )
+#define SOLDERPASTE_LAYER_THICKNESS pcbIUScale.mmToIU( 0.04 )
 
 
 CUSTOM_COLORS_LIST   BOARD_ADAPTER::g_SilkscreenColors;
@@ -331,7 +331,7 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR
 
     // Gives a non null size to avoid issues in zoom / scale calculations
     if( ( bbbox.GetWidth() == 0 ) && ( bbbox.GetHeight() == 0 ) )
-        bbbox.Inflate( Millimeter2iu( 10 ) );
+        bbbox.Inflate( pcbIUScale.mmToIU( 10 ) );
 
     m_boardSize = bbbox.GetSize();
     m_boardPos  = bbbox.Centre();
@@ -356,7 +356,7 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR
     m_nonCopperLayerThickness3DU   = DEFAULT_TECH_LAYER_THICKNESS * m_biuTo3Dunits;
     m_solderPasteLayerThickness3DU = SOLDERPASTE_LAYER_THICKNESS  * m_biuTo3Dunits;
 
-    g_BevelThickness3DU = Millimeter2iu( ADVANCED_CFG::GetCfg().m_3DRT_BevelHeight_um / 1000.0 ) * m_biuTo3Dunits;
+    g_BevelThickness3DU = pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_3DRT_BevelHeight_um / 1000.0 ) * m_biuTo3Dunits;
 
     if( m_board )
     {
@@ -667,7 +667,7 @@ bool BOARD_ADAPTER::createBoardPolygon( wxString* aErrorMsg )
             return false;
         }
 
-        int chainingEpsilon = Millimeter2iu( 0.02 );  // max dist from one endPt to next startPt
+        int chainingEpsilon = pcbIUScale.mmToIU( 0.02 ); // max dist from one endPt to next startPt
 
         success = BuildFootprintPolygonOutlines( m_board, m_board_poly,
                                                  m_board->GetDesignSettings().m_MaxError,
diff --git a/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp b/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp
index 47dc36a498..4ebdd58e11 100644
--- a/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp
+++ b/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp
@@ -1364,16 +1364,16 @@ void RENDER_3D_OPENGL::generate3dGrid( GRID3D_TYPE aGridType )
 
     brd_center_pos.y = -brd_center_pos.y;
 
-    const int xsize = std::max( brd_size.x, Millimeter2iu( 100 ) ) * 1.2;
-    const int ysize = std::max( brd_size.y, Millimeter2iu( 100 ) ) * 1.2;
+    const int xsize = std::max( brd_size.x, pcbIUScale.mmToIU( 100 ) ) * 1.2;
+    const int ysize = std::max( brd_size.y, pcbIUScale.mmToIU( 100 ) ) * 1.2;
 
     // Grid limits, in 3D units
     double  xmin = ( brd_center_pos.x - xsize / 2 ) * scale;
     double  xmax = ( brd_center_pos.x + xsize / 2 ) * scale;
     double  ymin = ( brd_center_pos.y - ysize / 2 ) * scale;
     double  ymax = ( brd_center_pos.y + ysize / 2 ) * scale;
-    double  zmin = Millimeter2iu( -50 ) * scale;
-    double  zmax = Millimeter2iu( 100 ) * scale;
+    double  zmin = pcbIUScale.mmToIU( -50 ) * scale;
+    double  zmax = pcbIUScale.mmToIU( 100 ) * scale;
 
     // Set rasterised line width (min value = 1)
     glLineWidth( 1 );
diff --git a/common/netclass.cpp b/common/netclass.cpp
index eba591f18e..837d10f4c6 100644
--- a/common/netclass.cpp
+++ b/common/netclass.cpp
@@ -31,15 +31,15 @@
 const char NETCLASS::Default[] = "Default";
 
 // Initial values for netclass initialization
-const int DEFAULT_CLEARANCE        = PcbMm2iu( 0.2 ); // track to track and track to pads clearance
-const int DEFAULT_VIA_DIAMETER     = PcbMm2iu( 0.8 );
-const int DEFAULT_VIA_DRILL        = PcbMm2iu( 0.4 );
-const int DEFAULT_UVIA_DIAMETER    = PcbMm2iu( 0.3 );
-const int DEFAULT_UVIA_DRILL       = PcbMm2iu( 0.1 );
-const int DEFAULT_TRACK_WIDTH      = PcbMm2iu( 0.25 );
-const int DEFAULT_DIFF_PAIR_WIDTH  = PcbMm2iu( 0.2 );
-const int DEFAULT_DIFF_PAIR_GAP    = PcbMm2iu( 0.25 );
-const int DEFAULT_DIFF_PAIR_VIAGAP = PcbMm2iu( 0.25 );
+const int DEFAULT_CLEARANCE        = pcbIUScale.mmToIU( 0.2 ); // track to track and track to pads clearance
+const int DEFAULT_VIA_DIAMETER     = pcbIUScale.mmToIU( 0.8 );
+const int DEFAULT_VIA_DRILL        = pcbIUScale.mmToIU( 0.4 );
+const int DEFAULT_UVIA_DIAMETER    = pcbIUScale.mmToIU( 0.3 );
+const int DEFAULT_UVIA_DRILL       = pcbIUScale.mmToIU( 0.1 );
+const int DEFAULT_TRACK_WIDTH      = pcbIUScale.mmToIU( 0.25 );
+const int DEFAULT_DIFF_PAIR_WIDTH  = pcbIUScale.mmToIU( 0.2 );
+const int DEFAULT_DIFF_PAIR_GAP    = pcbIUScale.mmToIU( 0.25 );
+const int DEFAULT_DIFF_PAIR_VIAGAP = pcbIUScale.mmToIU( 0.25 );
 
 const int DEFAULT_WIRE_WIDTH       = SchMils2iu( 6 );
 const int DEFAULT_BUS_WIDTH        = SchMils2iu( 12 );
diff --git a/common/pg_properties.cpp b/common/pg_properties.cpp
index da3ecfdfae..2c42641497 100644
--- a/common/pg_properties.cpp
+++ b/common/pg_properties.cpp
@@ -220,7 +220,7 @@ wxString PGPROPERTY_DISTANCE::DistanceToString( wxVariant& aVariant, int aArgFla
             return wxString::Format( wxT( "%g mils" ), Iu2Mils( aVariant.GetLong() ) );
 
         case EDA_UNITS::MILLIMETRES:
-            return wxString::Format( wxT( "%g mm" ), Iu2Millimeter( aVariant.GetLong() ) );
+            return wxString::Format( wxT( "%g mm" ), pcbIUScale.IUTomm( aVariant.GetLong() ) );
 
         case EDA_UNITS::UNSCALED:
             return wxString::Format( wxT( "%li" ), aVariant.GetLong() );
diff --git a/common/project/net_settings.cpp b/common/project/net_settings.cpp
index dc4677df27..544296655f 100644
--- a/common/project/net_settings.cpp
+++ b/common/project/net_settings.cpp
@@ -39,7 +39,7 @@ static std::optional<int> getInPcbUnits( const nlohmann::json& aObj, const std::
                                std::optional<int> aDefault = std::optional<int>() )
 {
     if( aObj.contains( aKey ) && aObj[aKey].is_number() )
-        return PcbMm2iu( aObj[aKey].get<double>() );
+        return pcbIUScale.mmToIU( aObj[aKey].get<double>() );
     else
         return aDefault;
 };
@@ -77,7 +77,7 @@ NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
                 auto saveInPcbUnits =
                         []( nlohmann::json& json, const std::string& aKey, int aValue )
                         {
-                            json.push_back( { aKey, PcbIu2mm( aValue ) } );
+                            json.push_back( { aKey, pcbIUScale.IUTomm( aValue ) } );
                         };
 
                 if( nc->HasClearance() )
diff --git a/eeschema/dialogs/dialog_plot_schematic.cpp b/eeschema/dialogs/dialog_plot_schematic.cpp
index 0d25871657..cbae82aac6 100644
--- a/eeschema/dialogs/dialog_plot_schematic.cpp
+++ b/eeschema/dialogs/dialog_plot_schematic.cpp
@@ -599,11 +599,11 @@ void DIALOG_PLOT_SCHEMATIC::setHpglPenWidth()
 {
     m_HPGLPenSize = m_penWidth.GetValue();
 
-    if( m_HPGLPenSize > Millimeter2iu( 2 ) )
-        m_HPGLPenSize = Millimeter2iu( 2 );
+    if( m_HPGLPenSize > schIUScale.mmToIU( 2 ) )
+        m_HPGLPenSize = schIUScale.mmToIU( 2 );
 
-    if( m_HPGLPenSize < Millimeter2iu( 0.01 ) )
-        m_HPGLPenSize = Millimeter2iu( 0.01 );
+    if( m_HPGLPenSize < schIUScale.mmToIU( 0.01 ) )
+        m_HPGLPenSize = schIUScale.mmToIU( 0.01 );
 }
 
 
@@ -728,7 +728,7 @@ bool DIALOG_PLOT_SCHEMATIC::plotOneSheetHpgl( const wxString&   aFileName,
     plotter->SetViewport( aPlot0ffset, IU_PER_MILS/10, aScale, false );
 
     // TODO this could be configurable
-    plotter->SetTargetChordLength( Millimeter2iu( 0.6 ) );
+    plotter->SetTargetChordLength( schIUScale.mmToIU( 0.6 ) );
 
     switch( aOriginAndUnits )
     {
diff --git a/eeschema/lib_pin.cpp b/eeschema/lib_pin.cpp
index dd61517713..ab98245929 100644
--- a/eeschema/lib_pin.cpp
+++ b/eeschema/lib_pin.cpp
@@ -550,7 +550,7 @@ void LIB_PIN::printPinElectricalTypeName( const RENDER_SETTINGS* aSettings, VECT
     // Use a reasonable (small) size to draw the text
     int         textSize = ( m_nameTextSize * 3 ) / 4;
 
-    #define ETXT_MAX_SIZE Millimeter2iu( 0.7 )
+    #define ETXT_MAX_SIZE schIUScale.mmToIU( 0.7 )
 
     if( textSize > ETXT_MAX_SIZE )
         textSize = ETXT_MAX_SIZE;
@@ -572,7 +572,7 @@ void LIB_PIN::printPinElectricalTypeName( const RENDER_SETTINGS* aSettings, VECT
         color = color.Mix( bg, 0.5f );
 
     VECTOR2I txtpos = aPosition;
-    int offset = Millimeter2iu( 0.4 );
+    int               offset = schIUScale.mmToIU( 0.4 );
     GR_TEXT_H_ALIGN_T hjustify = GR_TEXT_H_ALIGN_LEFT;
     EDA_ANGLE orient = ANGLE_HORIZONTAL;
 
@@ -1242,7 +1242,7 @@ const BOX2I LIB_PIN::GetBoundingBox( bool aIncludeInvisiblePins, bool aIncludeNa
 
     if( includeType )
     {
-        double   fontSize = std::max( m_nameTextSize * 3 / 4, Millimeter2iu( 0.7 ) );
+        double   fontSize = std::max( m_nameTextSize * 3 / 4, schIUScale.mmToIU( 0.7 ) );
         VECTOR2I typeTextSize = font->StringBoundaryLimits( GetElectricalTypeName(),
                                                             VECTOR2D( fontSize, fontSize ),
                                                             fontSize / 8.0, false, false );
diff --git a/eeschema/sch_marker.cpp b/eeschema/sch_marker.cpp
index 3e3c545d82..5095045e87 100644
--- a/eeschema/sch_marker.cpp
+++ b/eeschema/sch_marker.cpp
@@ -37,7 +37,7 @@
 #include <erc_item.h>
 
 /// Factor to convert the maker unit shape to internal units:
-#define SCALING_FACTOR  Millimeter2iu( 0.15 )
+#define SCALING_FACTOR schIUScale.mmToIU( 0.15 )
 
 
 SCH_MARKER::SCH_MARKER( std::shared_ptr<ERC_ITEM> aItem, const VECTOR2I& aPos ) :
diff --git a/eeschema/sch_painter.cpp b/eeschema/sch_painter.cpp
index 7d7e66834c..07a2b54b0b 100644
--- a/eeschema/sch_painter.cpp
+++ b/eeschema/sch_painter.cpp
@@ -1437,7 +1437,7 @@ void SCH_PAINTER::draw( const LIB_PIN *aPin, int aLayer, bool aDimmed )
 
     if( m_schSettings.m_ShowPinsElectricalType )
     {
-        size     [OUTSIDE] = std::max( aPin->GetNameTextSize() * 3 / 4, Millimeter2iu( 0.7 ) );
+        size[OUTSIDE] = std::max( aPin->GetNameTextSize() * 3 / 4, schIUScale.mmToIU( 0.7 ) );
         thickness[OUTSIDE] = float( size[OUTSIDE] ) / 8.0F;
         colour   [OUTSIDE] = getRenderColor( aPin, LAYER_PRIVATE_NOTES, drawingShadows );
         text     [OUTSIDE] = aPin->GetElectricalTypeName();
diff --git a/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp b/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp
index 1de70fc103..6376960652 100644
--- a/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp
+++ b/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp
@@ -2095,7 +2095,7 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadShapeVertices( const std::vector<VERTEX>& a
             // TODO: Load as arc...
 
             SHAPE_ARC        tempArc( centerPoint, startPoint, arcAngle );
-            SHAPE_LINE_CHAIN arcSegments = tempArc.ConvertToPolyline( Millimeter2iu( 0.1 ) );
+            SHAPE_LINE_CHAIN arcSegments = tempArc.ConvertToPolyline( schIUScale.mmToIU( 0.1 ) );
 
             // Load the arc as a series of piece-wise segments
 
diff --git a/eeschema/symbol_editor/symbol_edit_frame.cpp b/eeschema/symbol_editor/symbol_edit_frame.cpp
index 0c08326b0b..d3b65caf05 100644
--- a/eeschema/symbol_editor/symbol_edit_frame.cpp
+++ b/eeschema/symbol_editor/symbol_edit_frame.cpp
@@ -233,8 +233,8 @@ SYMBOL_EDIT_FRAME::SYMBOL_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
 
     // Set the working/draw area size to display a symbol to a reasonable value:
     // A 600mm x 600mm with a origin at the area center looks like a large working area
-    double max_size_x = Millimeter2iu( 600 );
-    double max_size_y = Millimeter2iu( 600 );
+    double max_size_x = schIUScale.mmToIU( 600 );
+    double max_size_y = schIUScale.mmToIU( 600 );
     BOX2D bbox;
     bbox.SetOrigin( -max_size_x /2, -max_size_y/2 );
     bbox.SetSize( max_size_x, max_size_y );
@@ -1300,8 +1300,8 @@ const BOX2I SYMBOL_EDIT_FRAME::GetDocumentExtents( bool aIncludeAllVisible ) con
     if( !m_symbol )
     {
         // Gives a reasonable drawing area size
-        int width = Millimeter2iu( 50 );
-        int height = Millimeter2iu( 30 );
+        int width = schIUScale.mmToIU( 50 );
+        int height = schIUScale.mmToIU( 30 );
 
         return BOX2I( VECTOR2I( -width/2, -height/2 ),
                       VECTOR2I( width, height ) );
diff --git a/eeschema/symbol_viewer_frame.cpp b/eeschema/symbol_viewer_frame.cpp
index ce8b6983a2..d246999263 100644
--- a/eeschema/symbol_viewer_frame.cpp
+++ b/eeschema/symbol_viewer_frame.cpp
@@ -280,8 +280,8 @@ SYMBOL_VIEWER_FRAME::SYMBOL_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAM
 
     // Set the working/draw area size to display a symbol to a reasonable value:
     // A 450mm x 450mm with a origin at the area center looks like a large working area
-    double max_size_x = Millimeter2iu( 450 );
-    double max_size_y = Millimeter2iu( 450 );
+    double max_size_x = schIUScale.mmToIU( 450 );
+    double max_size_y = schIUScale.mmToIU( 450 );
     BOX2D bbox;
     bbox.SetOrigin( -max_size_x / 2, -max_size_y / 2 );
     bbox.SetSize( max_size_x, max_size_y );
diff --git a/gerbview/dcode.cpp b/gerbview/dcode.cpp
index 033732aa35..ceca42daae 100644
--- a/gerbview/dcode.cpp
+++ b/gerbview/dcode.cpp
@@ -34,7 +34,7 @@
 #include <convert_to_biu.h>
 #include <convert_basic_shapes_to_polygon.h>
 
-#define DCODE_DEFAULT_SIZE Millimeter2iu( 0.1 )
+#define DCODE_DEFAULT_SIZE gerbIUScale.mmToIU( 0.1 )
 
 /* Format Gerber: NOTES:
  * Tools and D_CODES
diff --git a/gerbview/gerber_draw_item.cpp b/gerbview/gerber_draw_item.cpp
index 1684fce397..6a5814266c 100644
--- a/gerbview/gerber_draw_item.cpp
+++ b/gerbview/gerber_draw_item.cpp
@@ -777,7 +777,7 @@ BITMAPS GERBER_DRAW_ITEM::GetMenuImage() const
 bool GERBER_DRAW_ITEM::HitTest( const VECTOR2I& aRefPos, int aAccuracy ) const
 {
     // In case the item has a very tiny width defined, allow it to be selected
-    const int MIN_HIT_TEST_RADIUS = Millimeter2iu( 0.01 );
+    const int MIN_HIT_TEST_RADIUS = gerbIUScale.mmToIU( 0.01 );
 
     // calculate aRefPos in XY Gerber axis:
     VECTOR2I ref_pos = GetXYPosition( aRefPos );
@@ -968,7 +968,7 @@ double GERBER_DRAW_ITEM::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
 
         // the level of details is chosen experimentally, to show
         // only a readable text:
-        double level = (double)Millimeter2iu( 3 );
+        double level = (double) gerbIUScale.mmToIU( 3 );
         return level / ( size + 1 );
     }
 
diff --git a/gerbview/gerber_file_image.cpp b/gerbview/gerber_file_image.cpp
index 7faba0e2c1..1b2ecddfcf 100644
--- a/gerbview/gerber_file_image.cpp
+++ b/gerbview/gerber_file_image.cpp
@@ -359,8 +359,8 @@ void GERBER_FILE_IMAGE::DisplayImageInfo(  GERBVIEW_FRAME* aMainFrame  )
         break;
 
     case EDA_UNITS::MILLIMETRES:
-        msg.Printf( wxT( "X=%f Y=%f" ), Iu2Millimeter( m_ImageJustifyOffset.x ),
-                                        Iu2Millimeter( m_ImageJustifyOffset.y ) );
+        msg.Printf( wxT( "X=%f Y=%f" ), gerbIUScale.IUTomm( m_ImageJustifyOffset.x ),
+                                        gerbIUScale.IUTomm( m_ImageJustifyOffset.y ) );
         break;
 
     default:
diff --git a/gerbview/gerbview_painter.cpp b/gerbview/gerbview_painter.cpp
index 8c96fc3cfe..c82e1c9492 100644
--- a/gerbview/gerbview_painter.cpp
+++ b/gerbview/gerbview_painter.cpp
@@ -579,4 +579,4 @@ void GERBVIEW_PAINTER::drawApertureMacro( GERBER_DRAW_ITEM* aParent, bool aFille
 }
 
 
-const double GERBVIEW_RENDER_SETTINGS::MAX_FONT_SIZE = Millimeter2iu( 10.0 );
+const double GERBVIEW_RENDER_SETTINGS::MAX_FONT_SIZE = gerbIUScale.mmToIU( 10.0 );
diff --git a/include/convert_to_biu.h b/include/convert_to_biu.h
index 7b6d87d308..1f8f325c08 100644
--- a/include/convert_to_biu.h
+++ b/include/convert_to_biu.h
@@ -81,6 +81,13 @@ struct EDA_IU_SCALE
             IU_PER_MM( aIUPerMM ), IU_PER_MILS( aIUPerMM * 0.0254 )
     {
     }
+
+    constexpr inline double IUTomm( int iu ) const { return iu / IU_PER_MM; }
+
+    constexpr inline int mmToIU( double mm ) const
+    {
+        return (int) ( mm < 0 ? ( mm * IU_PER_MM - 0.5 ) : ( mm * IU_PER_MM + 0.5 ) );
+    }
 };
 
 constexpr EDA_IU_SCALE gerbIUScale = EDA_IU_SCALE( GERB_IU_PER_MM );
@@ -135,12 +142,6 @@ constexpr 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 )
-{
-    return iu / IU_PER_MM;
-}
-
 /// Convert mm to internal units (iu).
 // constexpr inline double Iu2Mils( int iu )
 // {
@@ -169,13 +170,4 @@ constexpr inline double SchIu2Mils( int iu )
     return iu / SCH_IU_PER_MILS;
 }
 
-constexpr inline int PcbMm2iu( double mm )
-{
-    return (int) ( mm < 0 ? mm * PCB_IU_PER_MM - 0.5 : mm * PCB_IU_PER_MM + 0.5 );
-}
-constexpr inline double PcbIu2mm( int iu )
-{
-    return iu / PCB_IU_PER_MM;
-}
-
 #endif
diff --git a/pagelayout_editor/dialogs/design_inspector.cpp b/pagelayout_editor/dialogs/design_inspector.cpp
index 31f47c29d7..8ccf644211 100644
--- a/pagelayout_editor/dialogs/design_inspector.cpp
+++ b/pagelayout_editor/dialogs/design_inspector.cpp
@@ -225,7 +225,8 @@ void DIALOG_INSPECTOR::ReCreateDesignList()
     GetGridList()->SetCellValue( row, COL_REPEAT_NUMBER, "-" );
     wxSize page_sizeIU = m_editorFrame->GetPageSizeIU();
     GetGridList()->SetCellValue( row, COL_TEXTSTRING, wxString::Format( _( "Size: %.1fx%.1fmm" ),
-                                 Iu2Millimeter( page_sizeIU.x ), Iu2Millimeter( page_sizeIU.y ) ) );
+                                                   drawSheetIUScale.IUTomm( page_sizeIU.x ),
+                                                   drawSheetIUScale.IUTomm( page_sizeIU.y ) ) );
     GetGridList()->SetCellRenderer (row, COL_BITMAP, new BitmapGridCellRenderer( root_xpm ) );
     GetGridList()->SetReadOnly( row, COL_BITMAP );
     m_itemsList.push_back( nullptr );   // this item is not a DS_DATA_ITEM, just a pseudo item
diff --git a/pagelayout_editor/pl_draw_panel_gal.cpp b/pagelayout_editor/pl_draw_panel_gal.cpp
index bfc714a639..9f0cb2bf2b 100644
--- a/pagelayout_editor/pl_draw_panel_gal.cpp
+++ b/pagelayout_editor/pl_draw_panel_gal.cpp
@@ -110,7 +110,7 @@ void PL_DRAW_PANEL_GAL::DisplayDrawingSheet()
     // of the selected corner for coord origin of new items
     // Not also this item has no peer in DS_DATA_MODEL list.
     const int penWidth = 0;     // This value is to use the default thickness line
-    constexpr double markerSize = Millimeter2iu( 5 );
+    constexpr double markerSize = drawSheetIUScale.mmToIU( 5 );
     m_pageDrawItem = std::make_unique<DS_DRAW_ITEM_PAGE>( penWidth, markerSize );
     m_view->Add( m_pageDrawItem.get() );
 
diff --git a/pcbnew/autorouter/ar_autoplacer.cpp b/pcbnew/autorouter/ar_autoplacer.cpp
index 1e099622a2..3c465eb873 100644
--- a/pcbnew/autorouter/ar_autoplacer.cpp
+++ b/pcbnew/autorouter/ar_autoplacer.cpp
@@ -65,7 +65,7 @@ AR_AUTOPLACER::AR_AUTOPLACER( BOARD* aBoard )
     for( FOOTPRINT* footprint : m_board->Footprints() )
         m_connectivity->Add( footprint );
 
-    m_gridSize = Millimeter2iu( STEP_AR_MM );
+    m_gridSize = pcbIUScale.mmToIU( STEP_AR_MM );
     m_progressReporter = nullptr;
     m_refreshCallback = nullptr;
     m_minCost = 0.0;
@@ -838,8 +838,8 @@ AR_RESULT AR_AUTOPLACER::AutoplaceFootprints( std::vector<FOOTPRINT*>& aFootprin
     m_matrix.m_GridRouting = m_gridSize; //(int) m_frame->GetScreen()->GetGridSize().x;
 
     // Ensure Board.m_GridRouting has a reasonable value:
-    if( m_matrix.m_GridRouting < Millimeter2iu( 0.25 ) )
-        m_matrix.m_GridRouting = Millimeter2iu( 0.25 );
+    if( m_matrix.m_GridRouting < pcbIUScale.mmToIU( 0.25 ) )
+        m_matrix.m_GridRouting = pcbIUScale.mmToIU( 0.25 );
 
     // Compute footprint parameters used in autoplace
     if( genPlacementRoutingMatrix( ) == 0 )
diff --git a/pcbnew/autorouter/spread_footprints.cpp b/pcbnew/autorouter/spread_footprints.cpp
index 19150a2f1a..c89d426685 100644
--- a/pcbnew/autorouter/spread_footprints.cpp
+++ b/pcbnew/autorouter/spread_footprints.cpp
@@ -276,7 +276,7 @@ void SpreadFootprints( std::vector<FOOTPRINT*>* aFootprints, VECTOR2I aSpreadAre
                     sub_area.SetWidth( placementArea.GetW()*scale );
                     sub_area.SetHeight( placementArea.GetH()*scale );
                     // Add a margin around the sheet placement area:
-                    sub_area.Inflate( Millimeter2iu( 1.5 ) );
+                    sub_area.Inflate( pcbIUScale.mmToIU( 1.5 ) );
 
                     placementSheetAreas.push_back( sub_area );
 
diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp
index b02d9f509f..7c6444b33f 100644
--- a/pcbnew/board.cpp
+++ b/pcbnew/board.cpp
@@ -94,7 +94,7 @@ BOARD::BOARD() :
     m_SolderMask = new ZONE( this );
     m_SolderMask->SetLayerSet( LSET().set( F_Mask ).set( B_Mask ) );
     m_SolderMask->SetOutline( new SHAPE_POLY_SET() );
-    int infinity = ( std::numeric_limits<int>::max() / 2 ) - Millimeter2iu( 1 );
+    int infinity = ( std::numeric_limits<int>::max() / 2 ) - pcbIUScale.mmToIU( 1 );
     m_SolderMask->Outline()->NewOutline();
     m_SolderMask->Outline()->Append( VECTOR2I( -infinity, -infinity ) );
     m_SolderMask->Outline()->Append( VECTOR2I( -infinity, +infinity ) );
@@ -1882,7 +1882,7 @@ ZONE* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode, PCB_LAYER_
 bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines,
                                      OUTLINE_ERROR_HANDLER* aErrorHandler )
 {
-    int chainingEpsilon = Millimeter2iu( 0.02 );  // max dist from one endPt to next startPt
+    int chainingEpsilon = pcbIUScale.mmToIU( 0.02 ); // max dist from one endPt to next startPt
 
     bool success = BuildBoardPolygonOutlines( this, aOutlines, GetDesignSettings().m_MaxError,
                                               chainingEpsilon, aErrorHandler );
diff --git a/pcbnew/board_design_settings.cpp b/pcbnew/board_design_settings.cpp
index 1e2bfc7a87..3f0eb24922 100644
--- a/pcbnew/board_design_settings.cpp
+++ b/pcbnew/board_design_settings.cpp
@@ -73,47 +73,47 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
     // Any following ones are freebies
     m_DefaultFPTextItems.emplace_back( wxT( "${REFERENCE}" ), true, F_Fab );
 
-    m_LineThickness[ LAYER_CLASS_SILK ] = Millimeter2iu( DEFAULT_SILK_LINE_WIDTH );
-    m_TextSize[ LAYER_CLASS_SILK ] = wxSize( Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ),
-                                             Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ) );
-    m_TextThickness[ LAYER_CLASS_SILK ] = Millimeter2iu( DEFAULT_SILK_TEXT_WIDTH );
+    m_LineThickness[ LAYER_CLASS_SILK ] = pcbIUScale.mmToIU( DEFAULT_SILK_LINE_WIDTH );
+    m_TextSize[ LAYER_CLASS_SILK ] = wxSize( pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE ),
+                                             pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE ) );
+    m_TextThickness[ LAYER_CLASS_SILK ] = pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_WIDTH );
     m_TextItalic[ LAYER_CLASS_SILK ] = false;
     m_TextUpright[ LAYER_CLASS_SILK ] = false;
 
-    m_LineThickness[ LAYER_CLASS_COPPER ] = Millimeter2iu( DEFAULT_COPPER_LINE_WIDTH );
-    m_TextSize[ LAYER_CLASS_COPPER ] = wxSize( Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE ),
-                                               Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE ) );
-    m_TextThickness[ LAYER_CLASS_COPPER ] = Millimeter2iu( DEFAULT_COPPER_TEXT_WIDTH );
+    m_LineThickness[ LAYER_CLASS_COPPER ] = pcbIUScale.mmToIU( DEFAULT_COPPER_LINE_WIDTH );
+    m_TextSize[ LAYER_CLASS_COPPER ] = wxSize( pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_SIZE ),
+                                               pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_SIZE ) );
+    m_TextThickness[ LAYER_CLASS_COPPER ] = pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_WIDTH );
     m_TextItalic[ LAYER_CLASS_COPPER ] = false;
     m_TextUpright[ LAYER_CLASS_COPPER ] = false;
 
     // Edges & Courtyards; text properties aren't used but better to have them holding
     // reasonable values than not.
-    m_LineThickness[ LAYER_CLASS_EDGES ] = Millimeter2iu( DEFAULT_EDGE_WIDTH );
-    m_TextSize[ LAYER_CLASS_EDGES ] = wxSize( Millimeter2iu( DEFAULT_TEXT_SIZE ),
-                                              Millimeter2iu( DEFAULT_TEXT_SIZE ) );
-    m_TextThickness[ LAYER_CLASS_EDGES ] = Millimeter2iu( DEFAULT_TEXT_WIDTH );
+    m_LineThickness[ LAYER_CLASS_EDGES ] = pcbIUScale.mmToIU( DEFAULT_EDGE_WIDTH );
+    m_TextSize[ LAYER_CLASS_EDGES ] = wxSize( pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ),
+                                              pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
+    m_TextThickness[ LAYER_CLASS_EDGES ] = pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH );
     m_TextItalic[ LAYER_CLASS_EDGES ] = false;
     m_TextUpright[ LAYER_CLASS_EDGES ] = false;
 
-    m_LineThickness[ LAYER_CLASS_COURTYARD ] = Millimeter2iu( DEFAULT_COURTYARD_WIDTH );
-    m_TextSize[ LAYER_CLASS_COURTYARD ] = wxSize( Millimeter2iu( DEFAULT_TEXT_SIZE ),
-                                                  Millimeter2iu( DEFAULT_TEXT_SIZE ) );
-    m_TextThickness[ LAYER_CLASS_COURTYARD ] = Millimeter2iu( DEFAULT_TEXT_WIDTH );
+    m_LineThickness[ LAYER_CLASS_COURTYARD ] = pcbIUScale.mmToIU( DEFAULT_COURTYARD_WIDTH );
+    m_TextSize[ LAYER_CLASS_COURTYARD ] = wxSize( pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ),
+                                                  pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
+    m_TextThickness[ LAYER_CLASS_COURTYARD ] = pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH );
     m_TextItalic[ LAYER_CLASS_COURTYARD ] = false;
     m_TextUpright[ LAYER_CLASS_COURTYARD ] = false;
 
-    m_LineThickness[ LAYER_CLASS_FAB ] = Millimeter2iu( DEFAULT_LINE_WIDTH );
-    m_TextSize[ LAYER_CLASS_FAB ] = wxSize( Millimeter2iu( DEFAULT_TEXT_SIZE ),
-                                                  Millimeter2iu( DEFAULT_TEXT_SIZE ) );
-    m_TextThickness[ LAYER_CLASS_FAB ] = Millimeter2iu( DEFAULT_TEXT_WIDTH );
+    m_LineThickness[ LAYER_CLASS_FAB ] = pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH );
+    m_TextSize[ LAYER_CLASS_FAB ] = wxSize( pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ),
+                                                  pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
+    m_TextThickness[ LAYER_CLASS_FAB ] = pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH );
     m_TextItalic[ LAYER_CLASS_FAB ] = false;
     m_TextUpright[ LAYER_CLASS_FAB ] = false;
 
-    m_LineThickness[ LAYER_CLASS_OTHERS ] = Millimeter2iu( DEFAULT_LINE_WIDTH );
-    m_TextSize[ LAYER_CLASS_OTHERS ] = wxSize( Millimeter2iu( DEFAULT_TEXT_SIZE ),
-                                               Millimeter2iu( DEFAULT_TEXT_SIZE ) );
-    m_TextThickness[ LAYER_CLASS_OTHERS ] = Millimeter2iu( DEFAULT_TEXT_WIDTH );
+    m_LineThickness[ LAYER_CLASS_OTHERS ] = pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH );
+    m_TextSize[ LAYER_CLASS_OTHERS ] = wxSize( pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ),
+                                               pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
+    m_TextThickness[ LAYER_CLASS_OTHERS ] = pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH );
     m_TextItalic[ LAYER_CLASS_OTHERS ] = false;
     m_TextUpright[ LAYER_CLASS_OTHERS ] = false;
 
@@ -124,33 +124,33 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
     m_DimensionTextPosition    = DIM_TEXT_POSITION::OUTSIDE;
     m_DimensionKeepTextAligned = true;
     m_DimensionArrowLength     = Mils2iu( DEFAULT_DIMENSION_ARROW_LENGTH );
-    m_DimensionExtensionOffset = Millimeter2iu( DEFAULT_DIMENSION_EXTENSION_OFFSET );
+    m_DimensionExtensionOffset = pcbIUScale.mmToIU( DEFAULT_DIMENSION_EXTENSION_OFFSET );
 
     m_useCustomTrackVia = false;
-    m_customTrackWidth  = Millimeter2iu( DEFAULT_CUSTOMTRACKWIDTH );
-    m_customViaSize.m_Diameter = Millimeter2iu( DEFAULT_VIASMINSIZE );
-    m_customViaSize.m_Drill = Millimeter2iu( DEFAULT_MINTHROUGHDRILL );
+    m_customTrackWidth  = pcbIUScale.mmToIU( DEFAULT_CUSTOMTRACKWIDTH );
+    m_customViaSize.m_Diameter = pcbIUScale.mmToIU( DEFAULT_VIASMINSIZE );
+    m_customViaSize.m_Drill = pcbIUScale.mmToIU( DEFAULT_MINTHROUGHDRILL );
 
     m_useCustomDiffPair = false;
-    m_customDiffPair.m_Width = Millimeter2iu( DEFAULT_CUSTOMDPAIRWIDTH );
-    m_customDiffPair.m_Gap = Millimeter2iu( DEFAULT_CUSTOMDPAIRGAP );
-    m_customDiffPair.m_ViaGap = Millimeter2iu( DEFAULT_CUSTOMDPAIRVIAGAP );
+    m_customDiffPair.m_Width = pcbIUScale.mmToIU( DEFAULT_CUSTOMDPAIRWIDTH );
+    m_customDiffPair.m_Gap = pcbIUScale.mmToIU( DEFAULT_CUSTOMDPAIRGAP );
+    m_customDiffPair.m_ViaGap = pcbIUScale.mmToIU( DEFAULT_CUSTOMDPAIRVIAGAP );
 
-    m_MinClearance        = Millimeter2iu( DEFAULT_MINCLEARANCE );
-    m_MinConn             = Millimeter2iu( DEFAULT_MINCONNECTION );
-    m_TrackMinWidth       = Millimeter2iu( DEFAULT_TRACKMINWIDTH );
-    m_ViasMinAnnularWidth = Millimeter2iu( DEFAULT_VIASMINSIZE - DEFAULT_MINTHROUGHDRILL ) / 2;
-    m_ViasMinSize         = Millimeter2iu( DEFAULT_VIASMINSIZE );
-    m_MinThroughDrill     = Millimeter2iu( DEFAULT_MINTHROUGHDRILL );
-    m_MicroViasMinSize    = Millimeter2iu( DEFAULT_MICROVIASMINSIZE );
-    m_MicroViasMinDrill   = Millimeter2iu( DEFAULT_MICROVIASMINDRILL );
-    m_CopperEdgeClearance = Millimeter2iu( DEFAULT_COPPEREDGECLEARANCE );
-    m_HoleClearance       = Millimeter2iu( DEFAULT_HOLECLEARANCE );
-    m_HoleToHoleMin       = Millimeter2iu( DEFAULT_HOLETOHOLEMIN );
-    m_SilkClearance       = Millimeter2iu( DEFAULT_SILKCLEARANCE );
+    m_MinClearance        = pcbIUScale.mmToIU( DEFAULT_MINCLEARANCE );
+    m_MinConn             = pcbIUScale.mmToIU( DEFAULT_MINCONNECTION );
+    m_TrackMinWidth       = pcbIUScale.mmToIU( DEFAULT_TRACKMINWIDTH );
+    m_ViasMinAnnularWidth = pcbIUScale.mmToIU( DEFAULT_VIASMINSIZE - DEFAULT_MINTHROUGHDRILL ) / 2;
+    m_ViasMinSize         = pcbIUScale.mmToIU( DEFAULT_VIASMINSIZE );
+    m_MinThroughDrill     = pcbIUScale.mmToIU( DEFAULT_MINTHROUGHDRILL );
+    m_MicroViasMinSize    = pcbIUScale.mmToIU( DEFAULT_MICROVIASMINSIZE );
+    m_MicroViasMinDrill   = pcbIUScale.mmToIU( DEFAULT_MICROVIASMINDRILL );
+    m_CopperEdgeClearance = pcbIUScale.mmToIU( DEFAULT_COPPEREDGECLEARANCE );
+    m_HoleClearance       = pcbIUScale.mmToIU( DEFAULT_HOLECLEARANCE );
+    m_HoleToHoleMin       = pcbIUScale.mmToIU( DEFAULT_HOLETOHOLEMIN );
+    m_SilkClearance       = pcbIUScale.mmToIU( DEFAULT_SILKCLEARANCE );
     m_MinResolvedSpokes   = DEFAULT_MINRESOLVEDSPOKES;
-    m_MinSilkTextHeight   = Millimeter2iu( DEFAULT_SILK_TEXT_SIZE * 0.8 );
-    m_MinSilkTextThickness= Millimeter2iu( DEFAULT_SILK_TEXT_WIDTH * 0.8 );
+    m_MinSilkTextHeight   = pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE * 0.8 );
+    m_MinSilkTextThickness= pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_WIDTH * 0.8 );
 
     for( int errorCode = DRCE_FIRST; errorCode <= DRCE_LAST; ++errorCode )
         m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR;
@@ -193,12 +193,12 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
     m_UseHeightForLengthCalcs = true;
 
     // Global mask margins:
-    m_SolderMaskExpansion = Millimeter2iu( DEFAULT_SOLDERMASK_EXPANSION );
-    m_SolderMaskMinWidth = Millimeter2iu( DEFAULT_SOLDERMASK_MIN_WIDTH );
-    m_SolderMaskToCopperClearance = Millimeter2iu( DEFAULT_SOLDERMASK_TO_COPPER_CLEARANCE );
+    m_SolderMaskExpansion = pcbIUScale.mmToIU( DEFAULT_SOLDERMASK_EXPANSION );
+    m_SolderMaskMinWidth = pcbIUScale.mmToIU( DEFAULT_SOLDERMASK_MIN_WIDTH );
+    m_SolderMaskToCopperClearance = pcbIUScale.mmToIU( DEFAULT_SOLDERMASK_TO_COPPER_CLEARANCE );
 
     // Solder paste margin absolute value
-    m_SolderPasteMargin = Millimeter2iu( DEFAULT_SOLDERPASTE_CLEARANCE );
+    m_SolderPasteMargin = pcbIUScale.mmToIU( DEFAULT_SOLDERPASTE_CLEARANCE );
     // Solder paste margin as a ratio of pad size
     // The final margin is the sum of these 2 values
     // Usually < 0 because the mask is smaller than pad
@@ -207,7 +207,7 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
     m_AllowSoldermaskBridgesInFPs = false;
 
     // Layer thickness for 3D viewer
-    m_boardThickness = Millimeter2iu( DEFAULT_BOARD_THICKNESS_MM );
+    m_boardThickness = pcbIUScale.mmToIU( DEFAULT_BOARD_THICKNESS_MM );
 
     m_viaSizeIndex = 0;
     m_trackWidthIndex = 0;
@@ -226,48 +226,48 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
             &m_UseHeightForLengthCalcs, true ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_clearance",
-            &m_MinClearance, Millimeter2iu( DEFAULT_MINCLEARANCE ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
+            &m_MinClearance, pcbIUScale.mmToIU( DEFAULT_MINCLEARANCE ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 25.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_connection",
-            &m_MinConn, Millimeter2iu( DEFAULT_MINCONNECTION ),
-            Millimeter2iu( 0.00 ), Millimeter2iu( 100.0 ), MM_PER_IU ) );
+            &m_MinConn, pcbIUScale.mmToIU( DEFAULT_MINCONNECTION ),
+            pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_track_width",
-            &m_TrackMinWidth, Millimeter2iu( DEFAULT_TRACKMINWIDTH ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
+            &m_TrackMinWidth, pcbIUScale.mmToIU( DEFAULT_TRACKMINWIDTH ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 25.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_annular_width",
-            &m_ViasMinAnnularWidth, Millimeter2iu( DEFAULT_VIASMINSIZE ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
+            &m_ViasMinAnnularWidth, pcbIUScale.mmToIU( DEFAULT_VIASMINSIZE ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 25.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_diameter",
-            &m_ViasMinSize, Millimeter2iu( DEFAULT_VIASMINSIZE ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
+            &m_ViasMinSize, pcbIUScale.mmToIU( DEFAULT_VIASMINSIZE ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 25.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_through_hole_diameter",
-            &m_MinThroughDrill, Millimeter2iu( DEFAULT_MINTHROUGHDRILL ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
+            &m_MinThroughDrill, pcbIUScale.mmToIU( DEFAULT_MINTHROUGHDRILL ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 25.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_diameter",
-            &m_MicroViasMinSize, Millimeter2iu( DEFAULT_MICROVIASMINSIZE ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 10.0 ), MM_PER_IU ) );
+            &m_MicroViasMinSize, pcbIUScale.mmToIU( DEFAULT_MICROVIASMINSIZE ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 10.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_drill",
-            &m_MicroViasMinDrill, Millimeter2iu( DEFAULT_MICROVIASMINDRILL ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 10.0 ), MM_PER_IU ) );
+            &m_MicroViasMinDrill, pcbIUScale.mmToIU( DEFAULT_MICROVIASMINDRILL ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 10.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_to_hole",
-            &m_HoleToHoleMin, Millimeter2iu( DEFAULT_HOLETOHOLEMIN ),
-            Millimeter2iu( 0.00 ), Millimeter2iu( 10.0 ), MM_PER_IU ) );
+            &m_HoleToHoleMin, pcbIUScale.mmToIU( DEFAULT_HOLETOHOLEMIN ),
+            pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_clearance",
-            &m_HoleClearance, Millimeter2iu( DEFAULT_HOLECLEARANCE ),
-            Millimeter2iu( 0.00 ), Millimeter2iu( 100.0 ), MM_PER_IU ) );
+            &m_HoleClearance, pcbIUScale.mmToIU( DEFAULT_HOLECLEARANCE ),
+            pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_silk_clearance",
-            &m_SilkClearance, Millimeter2iu( DEFAULT_SILKCLEARANCE ),
-            Millimeter2iu( 0.00 ), Millimeter2iu( 100.0 ), MM_PER_IU ) );
+            &m_SilkClearance, pcbIUScale.mmToIU( DEFAULT_SILKCLEARANCE ),
+            pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), MM_PER_IU ) );
 
     // While the maximum *effective* value is 4, we've had users interpret this as the count on
     // all layers, and enter something like 10.  They'll figure it out soon enough *unless* we
@@ -277,18 +277,18 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
             &m_MinResolvedSpokes, DEFAULT_MINRESOLVEDSPOKES, 0, 99 ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_height",
-            &m_MinSilkTextHeight, Millimeter2iu( DEFAULT_SILK_TEXT_SIZE * 0.8 ),
-            Millimeter2iu( 0.00 ), Millimeter2iu( 100.0 ), MM_PER_IU ) );
+            &m_MinSilkTextHeight, pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE * 0.8 ),
+            pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_thickness",
-            &m_MinSilkTextThickness, Millimeter2iu( DEFAULT_SILK_TEXT_WIDTH * 0.8 ),
-            Millimeter2iu( 0.00 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
+            &m_MinSilkTextThickness, pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_WIDTH * 0.8 ),
+            pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), MM_PER_IU ) );
 
     // Note: a clearance of -0.01 is a flag indicating we should use the legacy (pre-6.0) method
     // based on the edge cut thicknesses.
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_copper_edge_clearance",
-            &m_CopperEdgeClearance, Millimeter2iu( LEGACY_COPPEREDGECLEARANCE ),
-            Millimeter2iu( -0.01 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
+            &m_CopperEdgeClearance, pcbIUScale.mmToIU( LEGACY_COPPEREDGECLEARANCE ),
+            pcbIUScale.mmToIU( -0.01 ), pcbIUScale.mmToIU( 25.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
             [&]() -> nlohmann::json
@@ -356,7 +356,7 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
                 nlohmann::json js = nlohmann::json::array();
 
                 for( const int& width : m_TrackWidthList )
-                    js.push_back( Iu2Millimeter( width ) );
+                    js.push_back( pcbIUScale.IUTomm( width ) );
 
                 return js;
             },
@@ -372,7 +372,7 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
                     if( entry.empty() )
                         continue;
 
-                    m_TrackWidthList.emplace_back( Millimeter2iu( entry.get<double>() ) );
+                    m_TrackWidthList.emplace_back( pcbIUScale.mmToIU( entry.get<double>() ) );
                 }
             },
             {} ) );
@@ -386,8 +386,8 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
                 {
                     nlohmann::json entry = {};
 
-                    entry["diameter"] = Iu2Millimeter( via.m_Diameter );
-                    entry["drill"]    = Iu2Millimeter( via.m_Drill );
+                    entry["diameter"] = pcbIUScale.IUTomm( via.m_Diameter );
+                    entry["drill"]    = pcbIUScale.IUTomm( via.m_Drill );
 
                     js.push_back( entry );
                 }
@@ -409,8 +409,8 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
                     if( !entry.contains( "diameter" ) || !entry.contains( "drill" ) )
                         continue;
 
-                    int diameter = Millimeter2iu( entry["diameter"].get<double>() );
-                    int drill    = Millimeter2iu( entry["drill"].get<double>() );
+                    int diameter = pcbIUScale.mmToIU( entry["diameter"].get<double>() );
+                    int drill    = pcbIUScale.mmToIU( entry["drill"].get<double>() );
 
                     m_ViasDimensionsList.emplace_back( VIA_DIMENSION( diameter, drill ) );
                 }
@@ -426,9 +426,9 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
                 {
                     nlohmann::json entry = {};
 
-                    entry["width"]   = Iu2Millimeter( pair.m_Width );
-                    entry["gap"]     = Iu2Millimeter( pair.m_Gap );
-                    entry["via_gap"] = Iu2Millimeter( pair.m_ViaGap );
+                    entry["width"]   = pcbIUScale.IUTomm( pair.m_Width );
+                    entry["gap"]     = pcbIUScale.IUTomm( pair.m_Gap );
+                    entry["via_gap"] = pcbIUScale.IUTomm( pair.m_ViaGap );
 
                     js.push_back( entry );
                 }
@@ -451,9 +451,9 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
                             || !entry.contains( "via_gap" ) )
                         continue;
 
-                    int width   = Millimeter2iu( entry["width"].get<double>() );
-                    int gap     = Millimeter2iu( entry["gap"].get<double>() );
-                    int via_gap = Millimeter2iu( entry["via_gap"].get<double>() );
+                    int width   = pcbIUScale.mmToIU( entry["width"].get<double>() );
+                    int gap     = pcbIUScale.mmToIU( entry["gap"].get<double>() );
+                    int via_gap = pcbIUScale.mmToIU( entry["via_gap"].get<double>() );
 
                     m_DiffPairDimensionsList.emplace_back(
                             DIFF_PAIR_DIMENSION( width, gap, via_gap ) );
@@ -526,8 +526,8 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
                     TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)ii );
 
                     entry["td_target_name"]  = GetTeardropTargetCanonicalName( (TARGET_TD)ii );
-                    entry["td_maxlen"]  = Iu2Millimeter( td_prm->m_TdMaxLen );
-                    entry["td_maxheight"]  = Iu2Millimeter( td_prm->m_TdMaxHeight );
+                    entry["td_maxlen"]  = pcbIUScale.IUTomm( td_prm->m_TdMaxLen );
+                    entry["td_maxheight"]  = pcbIUScale.IUTomm( td_prm->m_TdMaxHeight );
                     entry["td_length_ratio"]  = td_prm->m_LengthRatio;
                     entry["td_height_ratio"]  = td_prm->m_HeightRatio;
                     entry["td_curve_segcount"]  = td_prm->m_CurveSegCount;
@@ -558,10 +558,10 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
                         TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)idx );
 
                         if( entry.contains( "td_maxlen" ) )
-                            td_prm->m_TdMaxLen = Millimeter2iu( entry["td_maxlen"].get<double>() );
+                            td_prm->m_TdMaxLen = pcbIUScale.mmToIU( entry["td_maxlen"].get<double>() );
 
                         if( entry.contains( "td_maxheight" ) )
-                            td_prm->m_TdMaxHeight = Millimeter2iu( entry["td_maxheight"].get<double>() );
+                            td_prm->m_TdMaxHeight = pcbIUScale.mmToIU( entry["td_maxheight"].get<double>() );
 
                         if( entry.contains( "td_length_ratio" ) )
                             td_prm->m_LengthRatio = entry["td_length_ratio"].get<double>();
@@ -580,19 +580,19 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
             {} ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_line_width",
-            &m_LineThickness[LAYER_CLASS_SILK], Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
+            &m_LineThickness[LAYER_CLASS_SILK], pcbIUScale.mmToIU( DEFAULT_SILK_LINE_WIDTH ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_v",
-            &m_TextSize[LAYER_CLASS_SILK].y, Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ),
+            &m_TextSize[LAYER_CLASS_SILK].y, pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE ),
             TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_h",
-            &m_TextSize[LAYER_CLASS_SILK].x, Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ),
+            &m_TextSize[LAYER_CLASS_SILK].x, pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE ),
             TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_thickness",
-            &m_TextThickness[LAYER_CLASS_SILK], Millimeter2iu( DEFAULT_SILK_TEXT_WIDTH ), 1,
+            &m_TextThickness[LAYER_CLASS_SILK], pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_WIDTH ), 1,
             TEXTS_MAX_WIDTH, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_italic",
@@ -602,20 +602,20 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
             &m_TextUpright[ LAYER_CLASS_SILK ], true ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_line_width",
-            &m_LineThickness[LAYER_CLASS_COPPER], Millimeter2iu( DEFAULT_COPPER_LINE_WIDTH ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
+            &m_LineThickness[LAYER_CLASS_COPPER], pcbIUScale.mmToIU( DEFAULT_COPPER_LINE_WIDTH ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_v",
-            &m_TextSize[LAYER_CLASS_COPPER].y, Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE ),
+            &m_TextSize[LAYER_CLASS_COPPER].y, pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_SIZE ),
             TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_h",
-            &m_TextSize[LAYER_CLASS_COPPER].x, Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE ),
+            &m_TextSize[LAYER_CLASS_COPPER].x, pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_SIZE ),
             TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_thickness",
-            &m_TextThickness[LAYER_CLASS_COPPER], Millimeter2iu( DEFAULT_COPPER_TEXT_WIDTH ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
+            &m_TextThickness[LAYER_CLASS_COPPER], pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_WIDTH ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_italic",
             &m_TextItalic[LAYER_CLASS_COPPER], false ) );
@@ -624,28 +624,28 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
             &m_TextUpright[LAYER_CLASS_COPPER], true ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.board_outline_line_width",
-            &m_LineThickness[LAYER_CLASS_EDGES], Millimeter2iu( DEFAULT_EDGE_WIDTH ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
+            &m_LineThickness[LAYER_CLASS_EDGES], pcbIUScale.mmToIU( DEFAULT_EDGE_WIDTH ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.courtyard_line_width",
-            &m_LineThickness[LAYER_CLASS_COURTYARD], Millimeter2iu( DEFAULT_COURTYARD_WIDTH ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
+            &m_LineThickness[LAYER_CLASS_COURTYARD], pcbIUScale.mmToIU( DEFAULT_COURTYARD_WIDTH ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_line_width",
-            &m_LineThickness[LAYER_CLASS_FAB], Millimeter2iu( DEFAULT_LINE_WIDTH ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
+            &m_LineThickness[LAYER_CLASS_FAB], pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_v",
-            &m_TextSize[LAYER_CLASS_FAB].y, Millimeter2iu( DEFAULT_TEXT_SIZE ),
+            &m_TextSize[LAYER_CLASS_FAB].y, pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ),
             TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_h",
-            &m_TextSize[LAYER_CLASS_FAB].x, Millimeter2iu( DEFAULT_TEXT_SIZE ),
+            &m_TextSize[LAYER_CLASS_FAB].x, pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ),
             TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_thickness",
-            &m_TextThickness[LAYER_CLASS_FAB], Millimeter2iu( DEFAULT_TEXT_WIDTH ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
+            &m_TextThickness[LAYER_CLASS_FAB], pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_italic",
             &m_TextItalic[LAYER_CLASS_FAB], false ) );
@@ -654,20 +654,20 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
             &m_TextUpright[LAYER_CLASS_FAB], true ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_line_width",
-            &m_LineThickness[LAYER_CLASS_OTHERS], Millimeter2iu( DEFAULT_LINE_WIDTH ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
+            &m_LineThickness[LAYER_CLASS_OTHERS], pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_v",
-            &m_TextSize[LAYER_CLASS_OTHERS].y, Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE,
+            &m_TextSize[LAYER_CLASS_OTHERS].y, pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE,
             TEXTS_MAX_SIZE, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_h",
-            &m_TextSize[LAYER_CLASS_OTHERS].x, Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE,
+            &m_TextSize[LAYER_CLASS_OTHERS].x, pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE,
             TEXTS_MAX_SIZE, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_thickness",
-            &m_TextThickness[LAYER_CLASS_OTHERS], Millimeter2iu( DEFAULT_TEXT_WIDTH ),
-            Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
+            &m_TextThickness[LAYER_CLASS_OTHERS], pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH ),
+            pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM<bool>( "defaults.other_text_italic",
             &m_TextItalic[LAYER_CLASS_OTHERS], false ) );
@@ -703,20 +703,20 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
 
     m_params.emplace_back( new PARAM<int>( "defaults.dimensions.extension_offset",
             &m_DimensionExtensionOffset,
-            Millimeter2iu( DEFAULT_DIMENSION_EXTENSION_OFFSET ) ) );
+            pcbIUScale.mmToIU( DEFAULT_DIMENSION_EXTENSION_OFFSET ) ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "defaults.zones.min_clearance",
             &m_defaultZoneSettings.m_ZoneClearance, Mils2iu( ZONE_CLEARANCE_MIL ),
-            Millimeter2iu( 0.0 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
+            pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "defaults.pads",
             [&]() -> nlohmann::json
             {
                 nlohmann::json ret =
                         {
-                            { "width",  Iu2Millimeter( m_Pad_Master->GetSize().x ) },
-                            { "height", Iu2Millimeter( m_Pad_Master->GetSize().y ) },
-                            { "drill",  Iu2Millimeter( m_Pad_Master->GetDrillSize().x ) }
+                            { "width",  pcbIUScale.IUTomm( m_Pad_Master->GetSize().x ) },
+                            { "height", pcbIUScale.IUTomm( m_Pad_Master->GetSize().y ) },
+                            { "drill",  pcbIUScale.IUTomm( m_Pad_Master->GetDrillSize().x ) }
                         };
 
                 return ret;
@@ -727,23 +727,23 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
                         && aJson.contains( "drill" ) )
                 {
                     wxSize sz;
-                    sz.SetWidth( Millimeter2iu( aJson["width"].get<double>() ) );
-                    sz.SetHeight( Millimeter2iu( aJson["height"].get<double>() ) );
+                    sz.SetWidth( pcbIUScale.mmToIU( aJson["width"].get<double>() ) );
+                    sz.SetHeight( pcbIUScale.mmToIU( aJson["height"].get<double>() ) );
 
                     m_Pad_Master->SetSize( sz );
 
-                    int drill = Millimeter2iu( aJson["drill"].get<double>() );
+                    int drill = pcbIUScale.mmToIU( aJson["drill"].get<double>() );
 
                     m_Pad_Master->SetDrillSize( wxSize( drill, drill ) );
                 }
             }, {} ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.max_error",
-            &m_MaxError, ARC_HIGH_DEF, Millimeter2iu( 0.0001 ), Millimeter2iu( 1.0 ), MM_PER_IU ) );
+            &m_MaxError, ARC_HIGH_DEF, pcbIUScale.mmToIU( 0.0001 ), pcbIUScale.mmToIU( 1.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "rules.solder_mask_to_copper_clearance",
-            &m_SolderMaskToCopperClearance, Millimeter2iu( DEFAULT_SOLDERMASK_TO_COPPER_CLEARANCE ),
-            Millimeter2iu( 0.0 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
+            &m_SolderMaskToCopperClearance, pcbIUScale.mmToIU( DEFAULT_SOLDERMASK_TO_COPPER_CLEARANCE ),
+            pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM<bool>( "zones_allow_external_fillets",
             &m_ZoneKeepExternalFillets, false ) );
@@ -1221,13 +1221,13 @@ int BOARD_DESIGN_SETTINGS::GetLayerClass( PCB_LAYER_ID aLayer ) const
 
 int BOARD_DESIGN_SETTINGS::GetDRCEpsilon() const
 {
-    return Millimeter2iu( ADVANCED_CFG::GetCfg().m_DRCEpsilon );
+    return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_DRCEpsilon );
 }
 
 
 int BOARD_DESIGN_SETTINGS::GetHolePlatingThickness() const
 {
-    return Millimeter2iu( ADVANCED_CFG::GetCfg().m_HoleWallThickness );
+    return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_HoleWallThickness );
 }
 
 
diff --git a/pcbnew/board_item.cpp b/pcbnew/board_item.cpp
index 540159c21e..1ee1f186e8 100644
--- a/pcbnew/board_item.cpp
+++ b/pcbnew/board_item.cpp
@@ -75,7 +75,7 @@ bool BOARD_ITEM::IsLocked() const
 
 STROKE_PARAMS BOARD_ITEM::GetStroke() const
 {
-    wxCHECK( false, STROKE_PARAMS( Millimeter2iu( DEFAULT_LINE_WIDTH ) ) );
+    wxCHECK( false, STROKE_PARAMS( pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ) ) );
 }
 
 
diff --git a/pcbnew/board_stackup_manager/board_stackup.cpp b/pcbnew/board_stackup_manager/board_stackup.cpp
index be72524bbd..8fcc1611a5 100644
--- a/pcbnew/board_stackup_manager/board_stackup.cpp
+++ b/pcbnew/board_stackup_manager/board_stackup.cpp
@@ -120,14 +120,14 @@ void BOARD_STACKUP_ITEM::RemoveDielectricPrms( int aDielectricPrmsIdx )
 int BOARD_STACKUP_ITEM::GetCopperDefaultThickness()
 {
     // A reasonable thickness for copper layers:
-    return Millimeter2iu( 0.035 );
+    return pcbIUScale.mmToIU( 0.035 );
 }
 
 
 int BOARD_STACKUP_ITEM::GetMaskDefaultThickness()
 {
     // A reasonable thickness for solder mask:
-    return Millimeter2iu( 0.01 );
+    return pcbIUScale.mmToIU( 0.01 );
 }
 
 
@@ -500,7 +500,7 @@ void BOARD_STACKUP::BuildDefaultStackupList( const BOARD_DESIGN_SETTINGS* aSetti
     if( aSettings == nullptr && aActiveCopperLayersCount > 0 )
         activeCuLayerCount = aActiveCopperLayersCount;
 
-    int brd__thickness = aSettings ? aSettings->GetBoardThickness() : Millimeter2iu( 1.6 );
+    int brd__thickness = aSettings ? aSettings->GetBoardThickness() : pcbIUScale.mmToIU( 1.6 );
     int diel_thickness = brd__thickness -
                          ( BOARD_STACKUP_ITEM::GetCopperDefaultThickness() * activeCuLayerCount );
 
diff --git a/pcbnew/convert_shape_list_to_polygon.cpp b/pcbnew/convert_shape_list_to_polygon.cpp
index ca0bbf70fa..f56cc63495 100644
--- a/pcbnew/convert_shape_list_to_polygon.cpp
+++ b/pcbnew/convert_shape_list_to_polygon.cpp
@@ -877,7 +877,7 @@ bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, int aE
 
         // Ensure non null area. If happen, gives a minimal size.
         if( ( bbbox.GetWidth() ) == 0 || ( bbbox.GetHeight() == 0 ) )
-            bbbox.Inflate( Millimeter2iu( 1.0 ) );
+            bbbox.Inflate( pcbIUScale.mmToIU( 1.0 ) );
 
         aOutlines.RemoveAllContours();
         aOutlines.NewOutline();
@@ -923,7 +923,7 @@ void buildBoardBoundingBoxPoly( const BOARD* aBoard, SHAPE_POLY_SET& aOutline )
 
     // Ensure non null area. If happen, gives a minimal size.
     if( ( bbbox.GetWidth() ) == 0 || ( bbbox.GetHeight() == 0 ) )
-        bbbox.Inflate( Millimeter2iu( 1.0 ) );
+        bbbox.Inflate( pcbIUScale.mmToIU( 1.0 ) );
 
     // Inflate slightly (by 1/10th the size of the box)
     bbbox.Inflate( bbbox.GetWidth() / 10, bbbox.GetHeight() / 10 );
diff --git a/pcbnew/dialogs/dialog_copper_zones.cpp b/pcbnew/dialogs/dialog_copper_zones.cpp
index 666b33bebd..ed8debf3a8 100644
--- a/pcbnew/dialogs/dialog_copper_zones.cpp
+++ b/pcbnew/dialogs/dialog_copper_zones.cpp
@@ -348,14 +348,14 @@ bool DIALOG_COPPER_ZONE::TransferDataToWindow()
     int bestvalue = m_settings.m_HatchThickness;
 
     if( bestvalue <= 0 )     // No defined value for m_HatchThickness
-        bestvalue = std::max( m_settings.m_ZoneMinThickness * 4, Millimeter2iu( 1.0 ) );
+        bestvalue = std::max( m_settings.m_ZoneMinThickness * 4, pcbIUScale.mmToIU( 1.0 ) );
 
     m_gridStyleThickness.SetValue( std::max( bestvalue, m_settings.m_ZoneMinThickness ) );
 
     bestvalue = m_settings.m_HatchGap;
 
     if( bestvalue <= 0 )     // No defined value for m_HatchGap
-        bestvalue = std::max( m_settings.m_ZoneMinThickness * 6, Millimeter2iu( 1.5 ) );
+        bestvalue = std::max( m_settings.m_ZoneMinThickness * 6, pcbIUScale.mmToIU( 1.5 ) );
 
     m_gridStyleGap.SetValue( std::max( bestvalue, m_settings.m_ZoneMinThickness ) );
 
@@ -544,8 +544,8 @@ bool DIALOG_COPPER_ZONE::AcceptOptions( bool aUseExportableSetupOnly )
     case 2: m_settings.m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL; break;
     }
 
-    if( !m_outlineHatchPitch.Validate( Millimeter2iu( ZONE_BORDER_HATCH_MINDIST_MM ),
-                                       Millimeter2iu( ZONE_BORDER_HATCH_MAXDIST_MM ) ) )
+    if( !m_outlineHatchPitch.Validate( pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MINDIST_MM ),
+                                       pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MAXDIST_MM ) ) )
         return false;
 
     m_settings.m_BorderHatchPitch = m_outlineHatchPitch.GetValue();
diff --git a/pcbnew/dialogs/dialog_create_array.cpp b/pcbnew/dialogs/dialog_create_array.cpp
index 01c88e9c9d..7cd7114c1c 100644
--- a/pcbnew/dialogs/dialog_create_array.cpp
+++ b/pcbnew/dialogs/dialog_create_array.cpp
@@ -45,8 +45,8 @@ struct CREATE_ARRAY_DIALOG_ENTRIES
             m_OptionsSet( true ),
             m_GridNx( 5 ),
             m_GridNy( 5 ),
-            m_GridDx( Millimeter2iu( 2.54 ) ),
-            m_GridDy( Millimeter2iu( 2.54 ) ),
+            m_GridDx( pcbIUScale.mmToIU( 2.54 ) ),
+            m_GridDy( pcbIUScale.mmToIU( 2.54 ) ),
             m_GridOffsetX( 0 ),
             m_GridOffsetY( 0 ),
             m_GridStagger( 1 ),
diff --git a/pcbnew/dialogs/dialog_export_step.cpp b/pcbnew/dialogs/dialog_export_step.cpp
index 861db0b769..a7645f7af1 100644
--- a/pcbnew/dialogs/dialog_export_step.cpp
+++ b/pcbnew/dialogs/dialog_export_step.cpp
@@ -337,10 +337,10 @@ void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
 
     // Check if the board outline is continuous
     // max dist from one endPt to next startPt to build a closed shape:
-    int chainingEpsilon = Millimeter2iu( tolerance );
+    int chainingEpsilon = pcbIUScale.mmToIU( tolerance );
 
     // Arc to segment approx error (not critical here: we do not use the outline shape):
-    int maxError = Millimeter2iu( 0.005 );
+    int maxError = pcbIUScale.mmToIU( 0.005 );
     bool success = BuildBoardPolygonOutlines( m_parent->GetBoard(), outline, maxError,
                                               chainingEpsilon, nullptr );
     if( !success )
@@ -435,8 +435,8 @@ void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
     case DIALOG_EXPORT_STEP::STEP_ORG_BOARD_CENTER:
     {
         BOX2I bbox = m_parent->GetBoard()->ComputeBoundingBox( true );
-        xOrg = Iu2Millimeter( bbox.GetCenter().x );
-        yOrg = Iu2Millimeter( bbox.GetCenter().y );
+        xOrg = pcbIUScale.IUTomm( bbox.GetCenter().x );
+        yOrg = pcbIUScale.IUTomm( bbox.GetCenter().y );
         LOCALE_IO dummy;
         cmdK2S.Append( wxString::Format( wxT( " --user-origin=%c%.6fx%.6fmm%c" ),
                                          quote, xOrg, yOrg, quote ) );
@@ -506,8 +506,8 @@ void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
     case DIALOG_EXPORT_STEP::STEP_ORG_BOARD_CENTER:
     {
         BOX2I bbox = m_parent->GetBoard()->ComputeBoundingBox( true );
-        xOrg = Iu2Millimeter( bbox.GetCenter().x );
-        yOrg = Iu2Millimeter( bbox.GetCenter().y );
+        xOrg = pcbIUScale.IUTomm( bbox.GetCenter().x );
+        yOrg = pcbIUScale.IUTomm( bbox.GetCenter().y );
         params.m_xOrigin = xOrg;
         params.m_yOrigin = yOrg;
         break;
diff --git a/pcbnew/dialogs/dialog_export_vrml.cpp b/pcbnew/dialogs/dialog_export_vrml.cpp
index 1b73fceb01..54bd605c59 100644
--- a/pcbnew/dialogs/dialog_export_vrml.cpp
+++ b/pcbnew/dialogs/dialog_export_vrml.cpp
@@ -232,8 +232,8 @@ void PCB_EDIT_FRAME::OnExportVRML( wxCommandEvent& event )
         // Origin = board center:
         BOARD* pcb = GetBoard();
         VECTOR2I center = pcb->GetBoundingBox().GetCenter();
-        aXRef = Iu2Millimeter( center.x );
-        aYRef = Iu2Millimeter( center.y );
+        aXRef = pcbIUScale.IUTomm( center.x );
+        aYRef = pcbIUScale.IUTomm( center.y );
     }
 
     double scale = scaleList[dlg.GetUnits()];     // final scale export
diff --git a/pcbnew/dialogs/dialog_non_copper_zones_properties.cpp b/pcbnew/dialogs/dialog_non_copper_zones_properties.cpp
index 2f07321add..c38c461216 100644
--- a/pcbnew/dialogs/dialog_non_copper_zones_properties.cpp
+++ b/pcbnew/dialogs/dialog_non_copper_zones_properties.cpp
@@ -191,14 +191,14 @@ bool DIALOG_NON_COPPER_ZONES_EDITOR::TransferDataToWindow()
     int bestvalue = m_settings.m_HatchThickness;
 
     if( bestvalue <= 0 )     // No defined value for m_hatchWidth
-        bestvalue = std::max( m_settings.m_ZoneMinThickness * 4, Millimeter2iu( 1.0 ) );
+        bestvalue = std::max( m_settings.m_ZoneMinThickness * 4, pcbIUScale.mmToIU( 1.0 ) );
 
     m_hatchWidth.SetValue( std::max( bestvalue, m_settings.m_ZoneMinThickness ) );
 
     bestvalue = m_settings.m_HatchGap;
 
     if( bestvalue <= 0 )     // No defined value for m_hatchGap
-        bestvalue = std::max( m_settings.m_ZoneMinThickness * 6, Millimeter2iu( 1.5 ) );
+        bestvalue = std::max( m_settings.m_ZoneMinThickness * 6, pcbIUScale.mmToIU( 1.5 ) );
 
     m_hatchGap.SetValue( std::max( bestvalue, m_settings.m_ZoneMinThickness ) );
 
@@ -262,8 +262,8 @@ bool DIALOG_NON_COPPER_ZONES_EDITOR::TransferDataFromWindow()
     case 2: m_settings.m_ZoneBorderDisplayStyle = ZONE_BORDER_DISPLAY_STYLE::DIAGONAL_FULL; break;
     }
 
-    if( !m_outlineHatchPitch.Validate( Millimeter2iu( ZONE_BORDER_HATCH_MINDIST_MM ),
-                                       Millimeter2iu( ZONE_BORDER_HATCH_MAXDIST_MM ) ) )
+    if( !m_outlineHatchPitch.Validate( pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MINDIST_MM ),
+                                       pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MAXDIST_MM ) ) )
         return false;
 
     m_settings.m_BorderHatchPitch = m_outlineHatchPitch.GetValue();
diff --git a/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp b/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp
index f4ec17a421..32a963fb4a 100644
--- a/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp
+++ b/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp
@@ -489,7 +489,7 @@ void DIALOG_PAD_PRIMITIVE_POLY_PROPS::onPaintPolyPanel( wxPaintEvent& event )
     dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
 
     // Calculate a suitable scale to fit the available draw area
-    int minsize( Millimeter2iu( 0.5 ) );
+    int minsize( pcbIUScale.mmToIU( 0.5 ) );
 
     for( unsigned ii = 0; ii < m_currPoints.size(); ++ii )
     {
diff --git a/pcbnew/dialogs/dialog_pad_properties.cpp b/pcbnew/dialogs/dialog_pad_properties.cpp
index 6750a4aba1..72ff1331aa 100644
--- a/pcbnew/dialogs/dialog_pad_properties.cpp
+++ b/pcbnew/dialogs/dialog_pad_properties.cpp
@@ -315,7 +315,7 @@ void DIALOG_PAD_PROPERTIES::prepareCanvas()
     KIGFX::COLOR4D axis_color = LIGHTBLUE;
 
     m_axisOrigin = new KIGFX::ORIGIN_VIEWITEM( axis_color, KIGFX::ORIGIN_VIEWITEM::CROSS,
-                                               Millimeter2iu( 0.2 ),
+                                               pcbIUScale.mmToIU( 0.2 ),
                                                VECTOR2D( m_dummyPad->GetPosition() ) );
     m_axisOrigin->SetDrawAtZero( true );
 
diff --git a/pcbnew/dialogs/dialog_plot.cpp b/pcbnew/dialogs/dialog_plot.cpp
index 7fb4ced0a8..4956e8012a 100644
--- a/pcbnew/dialogs/dialog_plot.cpp
+++ b/pcbnew/dialogs/dialog_plot.cpp
@@ -841,7 +841,7 @@ void DIALOG_PLOT::applyPlotSettings()
     }
 
     // Store m_PSWidthAdjust in mm in user config
-    cfg->m_Plot.ps_fine_width_adjust = Iu2Millimeter( m_PSWidthAdjust );
+    cfg->m_Plot.ps_fine_width_adjust = pcbIUScale.IUTomm( m_PSWidthAdjust );
 
     tempOptions.SetFormat( getPlotFormat() );
 
diff --git a/pcbnew/dialogs/dialog_rule_area_properties.cpp b/pcbnew/dialogs/dialog_rule_area_properties.cpp
index 4c0c29008b..791e18ae8a 100644
--- a/pcbnew/dialogs/dialog_rule_area_properties.cpp
+++ b/pcbnew/dialogs/dialog_rule_area_properties.cpp
@@ -221,8 +221,8 @@ bool DIALOG_RULE_AREA_PROPERTIES::TransferDataFromWindow()
         break;
     }
 
-    if( !m_outlineHatchPitch.Validate( Millimeter2iu( ZONE_BORDER_HATCH_MINDIST_MM ),
-                                       Millimeter2iu( ZONE_BORDER_HATCH_MAXDIST_MM ) ) )
+    if( !m_outlineHatchPitch.Validate( pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MINDIST_MM ),
+                                       pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MAXDIST_MM ) ) )
         return false;
 
     m_zonesettings.m_BorderHatchPitch = m_outlineHatchPitch.GetValue();
diff --git a/pcbnew/drc/drc_test_provider_library_parity.cpp b/pcbnew/drc/drc_test_provider_library_parity.cpp
index 22a3f1f40e..d86d3d86f6 100644
--- a/pcbnew/drc/drc_test_provider_library_parity.cpp
+++ b/pcbnew/drc/drc_test_provider_library_parity.cpp
@@ -212,7 +212,7 @@ bool shapesNeedUpdate( const FP_SHAPE* a, const FP_SHAPE* b )
 
         // Arc center is calculated and so may have round-off errors when parents are
         // differentially rotated.
-        if( ( a->GetCenter0() - b->GetCenter0() ).EuclideanNorm() > Millimeter2iu( 0.0001 ) )
+        if( ( a->GetCenter0() - b->GetCenter0() ).EuclideanNorm() > pcbIUScale.mmToIU( 0.0001 ) )
             return true;
 
         break;
diff --git a/pcbnew/drc/drc_test_provider_misc.cpp b/pcbnew/drc/drc_test_provider_misc.cpp
index 9b0cf11bbf..4467fb7400 100644
--- a/pcbnew/drc/drc_test_provider_misc.cpp
+++ b/pcbnew/drc/drc_test_provider_misc.cpp
@@ -96,7 +96,7 @@ void DRC_TEST_PROVIDER_MISC::testOutline()
 
     // Use a really tight chaining epsilon here so that we report errors that might affect
     // other tools (such as STEP export).
-    constexpr int chainingEpsilon = Millimeter2iu( 0.02 ) / 100;
+    constexpr int chainingEpsilon = pcbIUScale.mmToIU( 0.02 ) / 100;
 
     if( !BuildBoardPolygonOutlines( m_board, dummyOutline, m_board->GetDesignSettings().m_MaxError,
                                     chainingEpsilon, &errorHandler ) )
diff --git a/pcbnew/drc/drc_test_provider_sliver_checker.cpp b/pcbnew/drc/drc_test_provider_sliver_checker.cpp
index 62ec631c8a..c0d8cbd98c 100644
--- a/pcbnew/drc/drc_test_provider_sliver_checker.cpp
+++ b/pcbnew/drc/drc_test_provider_sliver_checker.cpp
@@ -84,7 +84,7 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
     if( !reportPhase( _( "Running sliver detection on copper layers..." ) ) )
         return false;   // DRC cancelled
 
-    int    widthTolerance = Millimeter2iu( ADVANCED_CFG::GetCfg().m_SliverWidthTolerance );
+    int    widthTolerance = pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SliverWidthTolerance );
     double angleTolerance = ADVANCED_CFG::GetCfg().m_SliverAngleTolerance;
     int    testLength = widthTolerance / ( 2 * sin( DEG2RAD( angleTolerance / 2 ) ) );
     LSET   copperLayerSet = m_drcEngine->GetBoard()->GetEnabledLayers() & LSET::AllCuMask();
diff --git a/pcbnew/exporters/export_idf.cpp b/pcbnew/exporters/export_idf.cpp
index 354e605bda..7d9ff4dbd2 100644
--- a/pcbnew/exporters/export_idf.cpp
+++ b/pcbnew/exporters/export_idf.cpp
@@ -40,14 +40,12 @@
 #include "3d_cache/3d_cache.h"
 #include "filename_resolver.h"
 
-#ifndef PCBNEW
-#define PCBNEW                  // needed to define the right value of Millimeter2iu(x)
-#endif
-#include <convert_to_biu.h>     // to define Millimeter2iu(x)
+
+#include <convert_to_biu.h>     // to define pcbIUScale.FromMillimeter(x)
 
 
 // assumed default graphical line thickness: == 0.1mm
-#define LINE_WIDTH (Millimeter2iu( 0.1 ))
+#define LINE_WIDTH (pcbIUScale.mmToIU( 0.1 ))
 
 
 static FILENAME_RESOLVER* resolver;
diff --git a/pcbnew/exporters/exporter_vrml.cpp b/pcbnew/exporters/exporter_vrml.cpp
index f5ae7c57ed..e053e645ca 100644
--- a/pcbnew/exporters/exporter_vrml.cpp
+++ b/pcbnew/exporters/exporter_vrml.cpp
@@ -115,7 +115,7 @@ EXPORTER_PCB_VRML::EXPORTER_PCB_VRML( BOARD* aBoard ) :
         m_layer_z[i] = 0;
 
     // this default only makes sense if the output is in mm
-    m_brd_thickness = Iu2Millimeter( m_board->GetDesignSettings().GetBoardThickness() );
+    m_brd_thickness = pcbIUScale.IUTomm( m_board->GetDesignSettings().GetBoardThickness() );
 
     // TODO: figure out a way to share all these stackup color definitions...
     initStaticColorList();
@@ -544,7 +544,7 @@ void EXPORTER_PCB_VRML::writeLayers( const char* aFileName, OSTREAM* aOutputFile
     // VRML_LAYER board;
     m_3D_board.Tesselate( &m_holes );
     double brdz = m_brd_thickness / 2.0
-                  - ( Millimeter2iu( ART_OFFSET / 2.0 ) ) * m_BoardToVrmlScale;
+                  - ( pcbIUScale.mmToIU( ART_OFFSET / 2.0 ) ) * m_BoardToVrmlScale;
 
     if( m_UseInlineModelsInBrdfile )
     {
@@ -577,14 +577,14 @@ void EXPORTER_PCB_VRML::writeLayers( const char* aFileName, OSTREAM* aOutputFile
     {
         write_triangle_bag( *aOutputFile, GetColor( VRML_COLOR_PASTE ),
                             &m_top_paste, true, true,
-                            GetLayerZ( F_Cu ) + Millimeter2iu( ART_OFFSET / 2.0 ) *
+                            GetLayerZ( F_Cu ) + pcbIUScale.mmToIU( ART_OFFSET / 2.0 ) *
                             m_BoardToVrmlScale,
                             0 );
     }
     else
     {
         create_vrml_plane( m_OutputPCB, VRML_COLOR_PASTE, &m_top_paste,
-                           GetLayerZ( F_Cu ) + Millimeter2iu( ART_OFFSET / 2.0 ) *
+                           GetLayerZ( F_Cu ) + pcbIUScale.mmToIU( ART_OFFSET / 2.0 ) *
                            m_BoardToVrmlScale,
                            true );
     }
@@ -596,14 +596,14 @@ void EXPORTER_PCB_VRML::writeLayers( const char* aFileName, OSTREAM* aOutputFile
     {
         write_triangle_bag( *aOutputFile, GetColor( VRML_COLOR_TOP_SOLDMASK ),
                             &m_top_soldermask, true, true,
-                            GetLayerZ( F_Cu ) + Millimeter2iu( ART_OFFSET / 2.0 ) *
+                            GetLayerZ( F_Cu ) + pcbIUScale.mmToIU( ART_OFFSET / 2.0 ) *
                             m_BoardToVrmlScale,
                             0 );
     }
     else
     {
         create_vrml_plane( m_OutputPCB, VRML_COLOR_TOP_SOLDMASK, &m_top_soldermask,
-                           GetLayerZ( F_Cu ) + Millimeter2iu( ART_OFFSET / 2.0 ) *
+                           GetLayerZ( F_Cu ) + pcbIUScale.mmToIU( ART_OFFSET / 2.0 ) *
                            m_BoardToVrmlScale,
                            true );
     }
@@ -630,13 +630,13 @@ void EXPORTER_PCB_VRML::writeLayers( const char* aFileName, OSTREAM* aOutputFile
         write_triangle_bag( *aOutputFile, GetColor( VRML_COLOR_PASTE ),
                             &m_bot_paste, true, false,
                             GetLayerZ( B_Cu )
-                            - Millimeter2iu( ART_OFFSET / 2.0 ) * m_BoardToVrmlScale,
+                            - pcbIUScale.mmToIU( ART_OFFSET / 2.0 ) * m_BoardToVrmlScale,
                             0 );
     }
     else
     {
         create_vrml_plane( m_OutputPCB, VRML_COLOR_PASTE, &m_bot_paste,
-                           GetLayerZ( B_Cu ) - Millimeter2iu( ART_OFFSET / 2.0 ) *
+                           GetLayerZ( B_Cu ) - pcbIUScale.mmToIU( ART_OFFSET / 2.0 ) *
                            m_BoardToVrmlScale,
                            false );
     }
@@ -648,14 +648,14 @@ void EXPORTER_PCB_VRML::writeLayers( const char* aFileName, OSTREAM* aOutputFile
     {
         write_triangle_bag( *aOutputFile, GetColor( VRML_COLOR_BOT_SOLDMASK ),
                             &m_bot_soldermask, true, false,
-                            GetLayerZ( B_Cu ) - Millimeter2iu( ART_OFFSET / 2.0 ) *
+                            GetLayerZ( B_Cu ) - pcbIUScale.mmToIU( ART_OFFSET / 2.0 ) *
                             m_BoardToVrmlScale,
                             0 );
     }
     else
     {
         create_vrml_plane( m_OutputPCB, VRML_COLOR_BOT_SOLDMASK, &m_bot_soldermask,
-                           GetLayerZ( B_Cu ) - Millimeter2iu( ART_OFFSET / 2.0 ) *
+                           GetLayerZ( B_Cu ) - pcbIUScale.mmToIU( ART_OFFSET / 2.0 ) *
                            m_BoardToVrmlScale,
                            false );
     }
@@ -667,17 +667,17 @@ void EXPORTER_PCB_VRML::writeLayers( const char* aFileName, OSTREAM* aOutputFile
     {
         write_triangle_bag( *aOutputFile, GetColor( VRML_COLOR_PASTE ),
                             &m_plated_holes, false, false,
-                            GetLayerZ( F_Cu ) + Millimeter2iu( ART_OFFSET / 2.0 ) *
+                            GetLayerZ( F_Cu ) + pcbIUScale.mmToIU( ART_OFFSET / 2.0 ) *
                             m_BoardToVrmlScale,
-                            GetLayerZ( B_Cu ) - Millimeter2iu( ART_OFFSET / 2.0 ) *
+                            GetLayerZ( B_Cu ) - pcbIUScale.mmToIU( ART_OFFSET / 2.0 ) *
                             m_BoardToVrmlScale );
     }
     else
     {
         create_vrml_shell( m_OutputPCB, VRML_COLOR_PASTE, &m_plated_holes,
-                           GetLayerZ( F_Cu ) + Millimeter2iu( ART_OFFSET / 2.0 ) *
+                           GetLayerZ( F_Cu ) + pcbIUScale.mmToIU( ART_OFFSET / 2.0 ) *
                            m_BoardToVrmlScale,
-                           GetLayerZ( B_Cu ) - Millimeter2iu( ART_OFFSET / 2.0 ) *
+                           GetLayerZ( B_Cu ) - pcbIUScale.mmToIU( ART_OFFSET / 2.0 ) *
                            m_BoardToVrmlScale );
     }
 
@@ -734,7 +734,7 @@ void EXPORTER_PCB_VRML::ComputeLayer3D_Zpos()
     }
 
     // To avoid rounding interference, we apply an epsilon to each successive layer
-    double epsilon_z = Millimeter2iu( ART_OFFSET ) * m_BoardToVrmlScale;
+    double epsilon_z = pcbIUScale.mmToIU( ART_OFFSET ) * m_BoardToVrmlScale;
     SetLayerZ( B_Paste, -half_thickness - epsilon_z );
     SetLayerZ( B_Adhes, -half_thickness - epsilon_z );
     SetLayerZ( B_SilkS, -half_thickness - epsilon_z * 3 );
@@ -857,7 +857,7 @@ void EXPORTER_PCB_VRML::ExportVrmlViaHoles()
         if( m_UseInlineModelsInBrdfile )
             max_error /= 2.54;      // The board is exported with a size reduced by 2.54
 
-        int nsides = GetArcToSegmentCount( via->GetDrillValue(), Millimeter2iu( max_error ),
+        int nsides = GetArcToSegmentCount( via->GetDrillValue(), pcbIUScale.mmToIU( max_error ),
                                            FULL_CIRCLE );
 
         double minSegLength = M_PI * 2.0 * hole_radius / nsides;
@@ -891,7 +891,7 @@ void EXPORTER_PCB_VRML::ExportVrmlPadHole( PAD* aPad )
         if( m_UseInlineModelsInBrdfile )
             max_error /= 2.54;      // The board is exported with a size reduced by 2.54
 
-        int nsides = GetArcToSegmentCount( hole_drill, Millimeter2iu( max_error ),
+        int nsides = GetArcToSegmentCount( hole_drill, pcbIUScale.mmToIU( max_error ),
                                            FULL_CIRCLE );
         double minSegLength = M_PI * hole_drill / nsides;
         double maxSegLength = minSegLength*2.0;
diff --git a/pcbnew/exporters/gen_drill_report_files.cpp b/pcbnew/exporters/gen_drill_report_files.cpp
index 54045af1c5..017e151de5 100644
--- a/pcbnew/exporters/gen_drill_report_files.cpp
+++ b/pcbnew/exporters/gen_drill_report_files.cpp
@@ -114,7 +114,7 @@ bool GENDRILL_WRITER_BASE::genDrillMapFile( const wxString& aFullFileName, PLOT_
         wxSize    pageSizeIU = pageA4.GetSizeIU( IU_PER_MILS );
 
         // Reserve a 10 mm margin around the page.
-        int margin = Millimeter2iu( 10 );
+        int margin = pcbIUScale.mmToIU( 10 );
 
         // Calculate a scaling factor to print the board on the sheet
         double Xscale = double( pageSizeIU.x - ( 2 * margin ) ) / bbbox.GetWidth();
@@ -171,7 +171,7 @@ bool GENDRILL_WRITER_BASE::genDrillMapFile( const wxString& aFullFileName, PLOT_
     plotter->SetColorMode( false );
 
     KIGFX::PCB_RENDER_SETTINGS renderSettings;
-    renderSettings.SetDefaultPenWidth( Millimeter2iu( 0.2 ) );
+    renderSettings.SetDefaultPenWidth( pcbIUScale.mmToIU( 0.2 ) );
 
     plotter->SetRenderSettings( &renderSettings );
 
@@ -239,7 +239,7 @@ bool GENDRILL_WRITER_BASE::genDrillMapFile( const wxString& aFullFileName, PLOT_
     int      intervalle = 0;
     char     line[1024];
     wxString msg;
-    int      textmarginaftersymbol = Millimeter2iu( 2 );
+    int      textmarginaftersymbol = pcbIUScale.mmToIU( 2 );
 
     // Set Drill Symbols width
     plotter->SetCurrentLineWidth( -1 );
@@ -248,7 +248,7 @@ bool GENDRILL_WRITER_BASE::genDrillMapFile( const wxString& aFullFileName, PLOT_
     plotDrillMarks( plotter );
 
     // Print a list of symbols used.
-    int    charSize = Millimeter2iu( 2 );  // text size in IUs
+    int    charSize = pcbIUScale.mmToIU( 2 );  // text size in IUs
 
     // real char scale will be 1/scale, because the global plot scale is scale
     // for scale < 1.0 ( plot bigger actual size)
@@ -289,7 +289,7 @@ bool GENDRILL_WRITER_BASE::genDrillMapFile( const wxString& aFullFileName, PLOT_
         if( bottom_limit && ( plotY+intervalle > bottom_limit ) )
         {
             plotY = bbbox.GetBottom() + intervalle;
-            plotX += max_line_len + Millimeter2iu( 10 );//column_width;
+            plotX += max_line_len + pcbIUScale.mmToIU( 10 );//column_width;
             max_line_len = 0;
         }
 
diff --git a/pcbnew/exporters/gerber_placefile_writer.cpp b/pcbnew/exporters/gerber_placefile_writer.cpp
index 799231106d..4f58167daf 100644
--- a/pcbnew/exporters/gerber_placefile_writer.cpp
+++ b/pcbnew/exporters/gerber_placefile_writer.cpp
@@ -114,10 +114,10 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, PCB_LAYER
     // Some tools in P&P files have the type and size defined.
     // they are position flash (round), pad1 flash (diamond), other pads flash (round)
     // and component outline thickness (polyline)
-    int flash_position_shape_diam = Millimeter2iu( 0.3 ); // defined size for position shape (circle)
-    int pad1_mark_size = Millimeter2iu( 0.36 );           // defined size for pad 1 position (diamond)
+    int flash_position_shape_diam = pcbIUScale.mmToIU( 0.3 ); // defined size for position shape (circle)
+    int pad1_mark_size = pcbIUScale.mmToIU( 0.36 );           // defined size for pad 1 position (diamond)
     int other_pads_mark_size = 0;                         // defined size for position shape (circle)
-    int line_thickness = Millimeter2iu( 0.1 );            // defined size for component outlines
+    int line_thickness = pcbIUScale.mmToIU( 0.1 );            // defined size for component outlines
 
     brd_plotter.SetLayerSet( LSET( aLayer ) );
     int cmp_count = 0;
diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp
index 493281603a..151451a1bd 100644
--- a/pcbnew/footprint.cpp
+++ b/pcbnew/footprint.cpp
@@ -811,7 +811,7 @@ const BOX2I FOOTPRINT::GetBoundingBox( bool aIncludeText, bool aIncludeInvisible
     }
 
     BOX2I bbox( m_pos );
-    bbox.Inflate( Millimeter2iu( 0.25 ) );   // Give a min size to the bbox
+    bbox.Inflate( pcbIUScale.mmToIU( 0.25 ) );   // Give a min size to the bbox
 
     for( BOARD_ITEM* item : m_drawings )
     {
@@ -967,7 +967,7 @@ SHAPE_POLY_SET FOOTPRINT::GetBoundingHull() const
     if( rawPolys.OutlineCount() == 0 )
     {
         // generate a small dummy rectangular outline around the anchor
-        const int halfsize = Millimeter2iu( 1.0 );
+        const int halfsize = pcbIUScale.mmToIU( 1.0 );
 
         rawPolys.NewOutline();
 
@@ -1799,8 +1799,8 @@ void FOOTPRINT::MoveAnchorPosition( const VECTOR2I& aMoveVector )
     // Update the 3D models
     for( FP_3DMODEL& model : Models() )
     {
-        model.m_Offset.x += Iu2Millimeter( moveVector.x );
-        model.m_Offset.y -= Iu2Millimeter( moveVector.y );
+        model.m_Offset.x += pcbIUScale.IUTomm( moveVector.x );
+        model.m_Offset.y -= pcbIUScale.IUTomm( moveVector.y );
     }
 
     m_cachedBoundingBox.Move( moveVector );
@@ -2265,8 +2265,8 @@ void FOOTPRINT::BuildCourtyardCaches( OUTLINE_ERROR_HANDLER* aErrorHandler )
     if( !list_front.size() && !list_back.size() )
         return;
 
-    int errorMax = Millimeter2iu( 0.02 );         // max error for polygonization
-    int chainingEpsilon = Millimeter2iu( 0.02 );  // max dist from one endPt to next startPt
+    int errorMax = pcbIUScale.mmToIU( 0.02 );         // max error for polygonization
+    int chainingEpsilon = pcbIUScale.mmToIU( 0.02 );  // max dist from one endPt to next startPt
 
     if( ConvertOutlineToPolygon( list_front, m_courtyard_cache_front, errorMax, chainingEpsilon,
                                  aErrorHandler ) )
diff --git a/pcbnew/footprint_edit_frame.cpp b/pcbnew/footprint_edit_frame.cpp
index 397cb00685..07ceea8e05 100644
--- a/pcbnew/footprint_edit_frame.cpp
+++ b/pcbnew/footprint_edit_frame.cpp
@@ -663,7 +663,7 @@ const BOX2I FOOTPRINT_EDIT_FRAME::GetDocumentExtents( bool aIncludeAllVisible )
         else
         {
             BOX2I newFootprintBB( { 0, 0 }, { 0, 0 } );
-            newFootprintBB.Inflate( Millimeter2iu( 12 ) );
+            newFootprintBB.Inflate( pcbIUScale.mmToIU( 12 ) );
             return newFootprintBB;
         }
     }
diff --git a/pcbnew/footprint_editor_settings.cpp b/pcbnew/footprint_editor_settings.cpp
index 2341d147fd..b8092cf9fd 100644
--- a/pcbnew/footprint_editor_settings.cpp
+++ b/pcbnew/footprint_editor_settings.cpp
@@ -150,42 +150,42 @@ FOOTPRINT_EDITOR_SETTINGS::FOOTPRINT_EDITOR_SETTINGS() :
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_line_width",
             &m_DesignSettings.m_LineThickness[ LAYER_CLASS_SILK ],
-            Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 100.0 ),
+            pcbIUScale.mmToIU( DEFAULT_SILK_LINE_WIDTH ), pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 100.0 ),
             MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_size_h",
             &m_DesignSettings.m_TextSize[ LAYER_CLASS_SILK ].x,
-            Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
+            pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_size_v",
             &m_DesignSettings.m_TextSize[ LAYER_CLASS_SILK ].y,
-            Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
+            pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_thickness",
             &m_DesignSettings.m_TextThickness[ LAYER_CLASS_SILK ],
-            Millimeter2iu( DEFAULT_SILK_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
+            pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM<bool>( "design_settings.silk_text_italic",
             &m_DesignSettings.m_TextItalic[ LAYER_CLASS_SILK ], false ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_line_width",
             &m_DesignSettings.m_LineThickness[ LAYER_CLASS_COPPER ],
-            Millimeter2iu( DEFAULT_COPPER_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
+            pcbIUScale.mmToIU( DEFAULT_COPPER_LINE_WIDTH ), pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ),
             MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_size_h",
             &m_DesignSettings.m_TextSize[ LAYER_CLASS_COPPER ].x,
-            Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE,
+            pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE,
             MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_size_v",
             &m_DesignSettings.m_TextSize[ LAYER_CLASS_COPPER ].y,
-            Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE,
+            pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE,
             MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_thickness",
             &m_DesignSettings.m_TextThickness[ LAYER_CLASS_COPPER ],
-            Millimeter2iu( DEFAULT_COPPER_TEXT_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
+            pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_WIDTH ), pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ),
             MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM<bool>( "design_settings.copper_text_italic",
@@ -193,50 +193,50 @@ FOOTPRINT_EDITOR_SETTINGS::FOOTPRINT_EDITOR_SETTINGS() :
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.edge_line_width",
             &m_DesignSettings.m_LineThickness[ LAYER_CLASS_EDGES ],
-            Millimeter2iu( DEFAULT_EDGE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
+            pcbIUScale.mmToIU( DEFAULT_EDGE_WIDTH ), pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ),
             MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.courtyard_line_width",
             &m_DesignSettings.m_LineThickness[ LAYER_CLASS_COURTYARD ],
-            Millimeter2iu( DEFAULT_COURTYARD_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
+            pcbIUScale.mmToIU( DEFAULT_COURTYARD_WIDTH ), pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ),
             MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_line_width",
            &m_DesignSettings.m_LineThickness[ LAYER_CLASS_FAB ],
-           Millimeter2iu( DEFAULT_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
+           pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ),
            MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_size_h",
            &m_DesignSettings.m_TextSize[ LAYER_CLASS_FAB ].x,
-           Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
+           pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_size_v",
            &m_DesignSettings.m_TextSize[ LAYER_CLASS_FAB ].y,
-           Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
+           pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_thickness",
            &m_DesignSettings.m_TextThickness[ LAYER_CLASS_FAB ],
-           Millimeter2iu( DEFAULT_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
+           pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM<bool>( "design_settings.fab_text_italic",
             &m_DesignSettings.m_TextItalic[ LAYER_CLASS_FAB ], false ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_line_width",
            &m_DesignSettings.m_LineThickness[ LAYER_CLASS_OTHERS ],
-           Millimeter2iu( DEFAULT_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
+           pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), pcbIUScale.mmToIU( 0.01 ), pcbIUScale.mmToIU( 5.0 ),
            MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_size_h",
            &m_DesignSettings.m_TextSize[ LAYER_CLASS_OTHERS ].x,
-           Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
+           pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_size_v",
            &m_DesignSettings.m_TextSize[ LAYER_CLASS_OTHERS ].y,
-           Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
+           pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_thickness",
            &m_DesignSettings.m_TextThickness[ LAYER_CLASS_OTHERS ],
-           Millimeter2iu( DEFAULT_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
+           pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
 
     m_params.emplace_back( new PARAM<bool>( "design_settings.others_text_italic",
             &m_DesignSettings.m_TextItalic[ LAYER_CLASS_OTHERS ], false ) );
diff --git a/pcbnew/fp_text.cpp b/pcbnew/fp_text.cpp
index dfdb042989..14950e01b7 100644
--- a/pcbnew/fp_text.cpp
+++ b/pcbnew/fp_text.cpp
@@ -48,7 +48,7 @@ FP_TEXT::FP_TEXT( FOOTPRINT* aParentFootprint, TEXT_TYPE text_type ) :
     SetKeepUpright( true );
 
     // Set text thickness to a default value
-    SetTextThickness( Millimeter2iu( DEFAULT_TEXT_WIDTH ) );
+    SetTextThickness( pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH ) );
     SetLayer( F_SilkS );
 
     // Set position and give a default layer if a valid parent footprint exists
diff --git a/pcbnew/import_gfx/dialog_import_gfx.cpp b/pcbnew/import_gfx/dialog_import_gfx.cpp
index af7e7d0900..a2ec7c8759 100644
--- a/pcbnew/import_gfx/dialog_import_gfx.cpp
+++ b/pcbnew/import_gfx/dialog_import_gfx.cpp
@@ -134,9 +134,9 @@ DIALOG_IMPORT_GFX::~DIALOG_IMPORT_GFX()
     cfg->m_ImportGraphics.layer                 = m_SelLayerBox->GetLayerSelection();
     cfg->m_ImportGraphics.interactive_placement = m_placementInteractive;
     cfg->m_ImportGraphics.last_file             = m_textCtrlFileName->GetValue();
-    cfg->m_ImportGraphics.dxf_line_width        = Iu2Millimeter( m_defaultLineWidth.GetValue() );
-    cfg->m_ImportGraphics.origin_x              = Iu2Millimeter( m_xOrigin.GetValue() );
-    cfg->m_ImportGraphics.origin_y              = Iu2Millimeter( m_yOrigin.GetValue() );
+    cfg->m_ImportGraphics.dxf_line_width        = pcbIUScale.IUTomm( m_defaultLineWidth.GetValue() );
+    cfg->m_ImportGraphics.origin_x              = pcbIUScale.IUTomm( m_xOrigin.GetValue() );
+    cfg->m_ImportGraphics.origin_y              = pcbIUScale.IUTomm( m_yOrigin.GetValue() );
     cfg->m_ImportGraphics.dxf_units             = m_choiceDxfUnits->GetSelection();
 
     m_importScale = EDA_UNIT_UTILS::UI::DoubleValueFromString( m_importScaleCtrl->GetValue() );
@@ -230,7 +230,7 @@ bool DIALOG_IMPORT_GFX::TransferDataFromWindow()
             else
                 dxfPlugin->SetUnit( it->first );
 
-            m_importer->SetLineWidthMM( Iu2Millimeter( m_defaultLineWidth.GetValue() ) );
+            m_importer->SetLineWidthMM( pcbIUScale.IUTomm( m_defaultLineWidth.GetValue() ) );
         }
         else
         {
@@ -239,7 +239,7 @@ bool DIALOG_IMPORT_GFX::TransferDataFromWindow()
 
         m_importer->SetPlugin( std::move( plugin ) );
         m_importer->SetLayer( PCB_LAYER_ID( m_SelLayerBox->GetLayerSelection() ) );
-        m_importer->SetImportOffsetMM( { Iu2Millimeter( origin.x ), Iu2Millimeter( origin.y ) } );
+        m_importer->SetImportOffsetMM( { pcbIUScale.IUTomm( origin.x ), pcbIUScale.IUTomm( origin.y ) } );
 
         LOCALE_IO dummy;    // Ensure floats can be read.
 
diff --git a/pcbnew/import_gfx/dxf_import_plugin.cpp b/pcbnew/import_gfx/dxf_import_plugin.cpp
index 80706045eb..e0c6f4a9b3 100644
--- a/pcbnew/import_gfx/dxf_import_plugin.cpp
+++ b/pcbnew/import_gfx/dxf_import_plugin.cpp
@@ -84,7 +84,6 @@
 // the value 0.0218 is equivalent to about 5 degrees arc,
 #define MIN_BULGE 0.0218
 
-//#define SCALE_FACTOR(x) millimeter2iu(x)  /* no longer used */
 #define SCALE_FACTOR(x) (x)
 
 
diff --git a/pcbnew/import_gfx/graphics_importer_pcbnew.cpp b/pcbnew/import_gfx/graphics_importer_pcbnew.cpp
index 03ba49c998..e045006880 100644
--- a/pcbnew/import_gfx/graphics_importer_pcbnew.cpp
+++ b/pcbnew/import_gfx/graphics_importer_pcbnew.cpp
@@ -38,7 +38,7 @@
 GRAPHICS_IMPORTER_PCBNEW::GRAPHICS_IMPORTER_PCBNEW()
 {
     m_layer = Dwgs_User;
-    m_millimeterToIu = Millimeter2iu( 1.0 );
+    m_millimeterToIu = pcbIUScale.mmToIU( 1.0 );
 }
 
 
diff --git a/pcbnew/netlist_reader/board_netlist_updater.cpp b/pcbnew/netlist_reader/board_netlist_updater.cpp
index 04dce63278..99165b5147 100644
--- a/pcbnew/netlist_reader/board_netlist_updater.cpp
+++ b/pcbnew/netlist_reader/board_netlist_updater.cpp
@@ -114,7 +114,7 @@ VECTOR2I BOARD_NETLIST_UPDATER::estimateFootprintInsertionPosition()
         if( bbox.GetWidth() || bbox.GetHeight() )
         {
             bestPosition.x = bbox.Centre().x;
-            bestPosition.y = bbox.GetBottom() + Millimeter2iu( 10 );
+            bestPosition.y = bbox.GetBottom() + pcbIUScale.mmToIU( 10 );
         }
     }
     else
diff --git a/pcbnew/pad.cpp b/pcbnew/pad.cpp
index 9253508380..4b14314a63 100644
--- a/pcbnew/pad.cpp
+++ b/pcbnew/pad.cpp
@@ -461,7 +461,7 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const
 
             // Avoid degenerated shapes (0 length segments) that always create issues
             // For roundrect pad very near a circle, use only a circle
-            const int min_len = Millimeter2iu( 0.0001);
+            const int min_len = pcbIUScale.mmToIU( 0.0001);
 
             if( half_size.x < min_len && half_size.y < min_len )
             {
@@ -1430,7 +1430,7 @@ double PAD::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
         if( divisor == 0 )
             return HIDE;
 
-        return ( double ) Millimeter2iu( 5 ) / divisor;
+        return ( double ) pcbIUScale.mmToIU( 5 ) / divisor;
     }
 
     // Passed all tests; show.
diff --git a/pcbnew/pcb_base_frame.cpp b/pcbnew/pcb_base_frame.cpp
index ef63f7f74a..beed8060b9 100644
--- a/pcbnew/pcb_base_frame.cpp
+++ b/pcbnew/pcb_base_frame.cpp
@@ -418,7 +418,7 @@ void PCB_BASE_FRAME::FocusOnItems( std::vector<BOARD_ITEM*> aItems, PCB_LAYER_ID
             case PCB_FP_DIM_RADIAL_T:
             case PCB_FP_DIM_ORTHOGONAL_T:
                 item->TransformShapeWithClearanceToPolygon( itemPoly, aLayer, 0,
-                                                            Millimeter2iu( 0.1 ), ERROR_INSIDE );
+                                                            pcbIUScale.mmToIU( 0.1 ), ERROR_INSIDE );
                 break;
 
             case PCB_ZONE_T:
@@ -430,7 +430,7 @@ void PCB_BASE_FRAME::FocusOnItems( std::vector<BOARD_ITEM*> aItems, PCB_LAYER_ID
                 // large areas (can be easily a few minutes for large areas).
                 // so we used only the zone outline that usually do not have too many vertices.
                 zone->TransformShapeWithClearanceToPolygon( itemPoly, aLayer, 0,
-                                                            Millimeter2iu( 0.1 ), ERROR_INSIDE );
+                                                            pcbIUScale.FromMillimeter( 0.1 ), ERROR_INSIDE );
 
                 if( itemPoly.IsEmpty() )
                     itemPoly = *zone->Outline();
diff --git a/pcbnew/pcb_dimension.cpp b/pcbnew/pcb_dimension.cpp
index 2c2cf73f1a..b5aa368d0a 100644
--- a/pcbnew/pcb_dimension.cpp
+++ b/pcbnew/pcb_dimension.cpp
@@ -49,7 +49,7 @@ PCB_DIMENSION_BASE::PCB_DIMENSION_BASE( BOARD_ITEM* aParent, KICAD_T aType ) :
         m_unitsFormat( DIM_UNITS_FORMAT::BARE_SUFFIX ),
         m_precision( 4 ),
         m_suppressZeroes( false ),
-        m_lineThickness( Millimeter2iu( 0.2 ) ),
+        m_lineThickness( pcbIUScale.mmToIU( 0.2 ) ),
         m_arrowLength( Mils2iu( 50 ) ),
         m_extensionOffset( 0 ),
         m_textPosition( DIM_TEXT_POSITION::OUTSIDE ),
diff --git a/pcbnew/pcb_group.cpp b/pcbnew/pcb_group.cpp
index bdf4a12f59..8acb4fd027 100644
--- a/pcbnew/pcb_group.cpp
+++ b/pcbnew/pcb_group.cpp
@@ -227,7 +227,7 @@ const BOX2I PCB_GROUP::GetBoundingBox() const
     for( BOARD_ITEM* item : m_items )
         bbox.Merge( item->GetBoundingBox() );
 
-    bbox.Inflate( Millimeter2iu( 0.25 ) ); // Give a min size to the bbox
+    bbox.Inflate( pcbIUScale.mmToIU( 0.25 ) ); // Give a min size to the bbox
 
     return bbox;
 }
diff --git a/pcbnew/pcb_marker.cpp b/pcbnew/pcb_marker.cpp
index 7932b40853..7bb349eab4 100644
--- a/pcbnew/pcb_marker.cpp
+++ b/pcbnew/pcb_marker.cpp
@@ -40,7 +40,7 @@
 
 
 /// Factor to convert the maker unit shape to internal units:
-#define SCALING_FACTOR  Millimeter2iu( 0.1625 )
+#define SCALING_FACTOR  pcbIUScale.mmToIU( 0.1625 )
 
 
 
diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp
index 7cbfc80f2c..52aeed8992 100644
--- a/pcbnew/pcb_painter.cpp
+++ b/pcbnew/pcb_painter.cpp
@@ -1893,7 +1893,7 @@ void PCB_PAINTER::draw( const PCB_TEXTBOX* aTextBox, int aLayer )
         // Draw the box with a larger thickness than box thickness to show
         // the shadow mask
         std::vector<VECTOR2I> pts = aTextBox->GetCorners();
-        int line_thickness = std::max( thickness*3, Millimeter2iu( 0.2 ) );
+        int line_thickness = std::max( thickness*3, pcbIUScale.mmToIU( 0.2 ) );
 
         for( size_t ii = 0; ii < pts.size(); ++ii )
             m_gal->DrawSegment( pts[ ii ], pts[ (ii + 1) % pts.size() ], line_thickness );
@@ -2472,4 +2472,4 @@ void PCB_PAINTER::draw( const PCB_MARKER* aMarker, int aLayer )
 }
 
 
-const double PCB_RENDER_SETTINGS::MAX_FONT_SIZE = Millimeter2iu( 10.0 );
+const double PCB_RENDER_SETTINGS::MAX_FONT_SIZE = pcbIUScale.mmToIU( 10.0 );
diff --git a/pcbnew/pcb_plot_params.cpp b/pcbnew/pcb_plot_params.cpp
index 77597a1c6e..21cd083c56 100644
--- a/pcbnew/pcb_plot_params.cpp
+++ b/pcbnew/pcb_plot_params.cpp
@@ -138,7 +138,7 @@ PCB_PLOT_PARAMS::PCB_PLOT_PARAMS()
     m_skipNPTH_Pads              = false;
 
     // line width to plot items in outline mode.
-    m_sketchPadLineWidth         = Millimeter2iu( 0.1 );
+    m_sketchPadLineWidth         = pcbIUScale.mmToIU( 0.1 );
 
     m_default_colors = std::make_shared<COLOR_SETTINGS>();
     m_colors         = m_default_colors.get();
diff --git a/pcbnew/pcb_shape.cpp b/pcbnew/pcb_shape.cpp
index e9360f5815..89dd30332a 100644
--- a/pcbnew/pcb_shape.cpp
+++ b/pcbnew/pcb_shape.cpp
@@ -36,14 +36,14 @@
 
 PCB_SHAPE::PCB_SHAPE( BOARD_ITEM* aParent, KICAD_T aItemType, SHAPE_T aShapeType ) :
     BOARD_ITEM( aParent, aItemType ),
-    EDA_SHAPE( aShapeType, Millimeter2iu( DEFAULT_LINE_WIDTH ), FILL_T::NO_FILL )
+    EDA_SHAPE( aShapeType, pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), FILL_T::NO_FILL )
 {
 }
 
 
 PCB_SHAPE::PCB_SHAPE( BOARD_ITEM* aParent, SHAPE_T shapetype ) :
     BOARD_ITEM( aParent, PCB_SHAPE_T ),
-    EDA_SHAPE( shapetype, Millimeter2iu( DEFAULT_LINE_WIDTH ), FILL_T::NO_FILL )
+    EDA_SHAPE( shapetype, pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), FILL_T::NO_FILL )
 {
 }
 
diff --git a/pcbnew/pcb_target.cpp b/pcbnew/pcb_target.cpp
index aaedf58627..0b18bdf608 100644
--- a/pcbnew/pcb_target.cpp
+++ b/pcbnew/pcb_target.cpp
@@ -41,8 +41,8 @@ PCB_TARGET::PCB_TARGET( BOARD_ITEM* aParent ) :
     BOARD_ITEM( aParent, PCB_TARGET_T )
 {
     m_shape     = 0;
-    m_size      = Millimeter2iu( 5 );          // Gives a decent size
-    m_lineWidth = Millimeter2iu( DEFAULT_COPPER_LINE_WIDTH );
+    m_size      = pcbIUScale.mmToIU( 5 );          // Gives a decent size
+    m_lineWidth = pcbIUScale.mmToIU( DEFAULT_COPPER_LINE_WIDTH );
     m_layer     = Edge_Cuts;                   // a target is on all layers
 }
 
diff --git a/pcbnew/pcb_track.cpp b/pcbnew/pcb_track.cpp
index 2e223a2264..9fa6cd72ec 100644
--- a/pcbnew/pcb_track.cpp
+++ b/pcbnew/pcb_track.cpp
@@ -51,7 +51,7 @@ using KIGFX::PCB_RENDER_SETTINGS;
 PCB_TRACK::PCB_TRACK( BOARD_ITEM* aParent, KICAD_T idtype ) :
     BOARD_CONNECTED_ITEM( aParent, idtype )
 {
-    m_Width = Millimeter2iu( 0.2 );     // Gives a reasonable default width
+    m_Width = pcbIUScale.mmToIU( 0.2 );     // Gives a reasonable default width
 }
 
 
@@ -640,7 +640,7 @@ double PCB_TRACK::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
             return HIDE;
 
         // Netnames will be shown only if zoom is appropriate
-        return ( double ) Millimeter2iu( 4 ) / ( m_Width + 1 );
+        return ( double ) pcbIUScale.mmToIU( 4 ) / ( m_Width + 1 );
     }
 
     if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
@@ -765,7 +765,7 @@ double PCB_VIA::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
         }
 
         // Netnames will be shown only if zoom is appropriate
-        return m_Width == 0 ? HIDE : ( (double)Millimeter2iu( 10 ) / m_Width );
+        return m_Width == 0 ? HIDE : ( (double)pcbIUScale.mmToIU( 10 ) / m_Width );
     }
 
     // Passed all tests; show.
diff --git a/pcbnew/pcbnew_printout.cpp b/pcbnew/pcbnew_printout.cpp
index 864b2ceeff..ee25610ffc 100644
--- a/pcbnew/pcbnew_printout.cpp
+++ b/pcbnew/pcbnew_printout.cpp
@@ -244,7 +244,7 @@ void PCBNEW_PRINTOUT::setupPainter( KIGFX::PAINTER& aPainter )
         break;
 
     case PCBNEW_PRINTOUT_SETTINGS::SMALL_DRILL_SHAPE:
-        painter.SetDrillMarks( false, Millimeter2iu( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize ) );
+        painter.SetDrillMarks( false, pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize ) );
 
         painter.GetSettings()->SetLayerColor( LAYER_PAD_PLATEDHOLES, COLOR4D::BLACK );
         painter.GetSettings()->SetLayerColor( LAYER_NON_PLATEDHOLES, COLOR4D::BLACK );
diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp
index 9c57b3892d..826bfeb54d 100644
--- a/pcbnew/plot_board_layers.cpp
+++ b/pcbnew/plot_board_layers.cpp
@@ -729,7 +729,7 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
         if( aPlotOpt.GetDrillMarksType() != PCB_PLOT_PARAMS::NO_DRILL_SHAPE )
         {
             int smallDrill = ( aPlotOpt.GetDrillMarksType() == PCB_PLOT_PARAMS::SMALL_DRILL_SHAPE )
-                             ? Millimeter2iu( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize ) :
+                             ? pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize ) :
                              INT_MAX;
 
             for( FOOTPRINT* footprint : aBoard->Footprints() )
@@ -964,7 +964,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
 
     // Slightly inflate polygons to avoid any gap between them and other shapes,
     // These gaps are created by arc to segments approximations
-    areas.Inflate( Millimeter2iu( 0.002 ), 6 );
+    areas.Inflate( pcbIUScale.mmToIU( 0.002 ), 6 );
 
     // Now, only polygons with a too small thickness are stored in areas.
     areas.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
@@ -1174,7 +1174,7 @@ PLOTTER* StartPlotBoard( BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aL
 
     KIGFX::PCB_RENDER_SETTINGS* renderSettings = new KIGFX::PCB_RENDER_SETTINGS();
     renderSettings->LoadColors( aPlotOpts->ColorSettings() );
-    renderSettings->SetDefaultPenWidth( Millimeter2iu( 0.0212 ) );  // Hairline at 1200dpi
+    renderSettings->SetDefaultPenWidth( pcbIUScale.mmToIU( 0.0212 ) );  // Hairline at 1200dpi
 
     if( aLayer >= 0 && aLayer < GAL_LAYER_ID_END )
         renderSettings->SetLayerName( aBoard->GetLayerName( ToLAYER_ID( aLayer ) ) );
diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp
index 7984c3daac..c6f5cdc651 100644
--- a/pcbnew/plot_brditems_plotter.cpp
+++ b/pcbnew/plot_brditems_plotter.cpp
@@ -1113,7 +1113,7 @@ void BRDITEMS_PLOTTER::PlotDrillMarks()
     /* If small drills marks were requested prepare a clamp value to pass
        to the helper function */
     int smallDrill = GetDrillMarksType() == PCB_PLOT_PARAMS::SMALL_DRILL_SHAPE
-                    ? Millimeter2iu( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize ) : 0;
+                    ? pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize ) : 0;
 
     /* In the filled trace mode drill marks are drawn white-on-black to scrape
        the underlying pad. This works only for drivers supporting color change,
diff --git a/pcbnew/plugins/altium/altium_pcb.cpp b/pcbnew/plugins/altium/altium_pcb.cpp
index d32f8a87b1..d6774ec58b 100644
--- a/pcbnew/plugins/altium/altium_pcb.cpp
+++ b/pcbnew/plugins/altium/altium_pcb.cpp
@@ -1219,9 +1219,9 @@ void ALTIUM_PCB::ParseComponentsBodies6Data( const ALTIUM_COMPOUND_FILE&     aAl
 
         modelSettings.m_Filename = modelTuple->second;
 
-        modelSettings.m_Offset.x = Iu2Millimeter((int) elem.modelPosition.x - fpPosition.x );
-        modelSettings.m_Offset.y = -Iu2Millimeter((int) elem.modelPosition.y - fpPosition.y );
-        modelSettings.m_Offset.z = Iu2Millimeter( (int) elem.modelPosition.z );
+        modelSettings.m_Offset.x = pcbIUScale.IUTomm((int) elem.modelPosition.x - fpPosition.x );
+        modelSettings.m_Offset.y = -pcbIUScale.IUTomm((int) elem.modelPosition.y - fpPosition.y );
+        modelSettings.m_Offset.z = pcbIUScale.IUTomm( (int) elem.modelPosition.z );
 
         EDA_ANGLE orientation = footprint->GetOrientation();
 
diff --git a/pcbnew/plugins/eagle/eagle_plugin.cpp b/pcbnew/plugins/eagle/eagle_plugin.cpp
index a08d7ad2a3..9ab4561a65 100644
--- a/pcbnew/plugins/eagle/eagle_plugin.cpp
+++ b/pcbnew/plugins/eagle/eagle_plugin.cpp
@@ -1883,15 +1883,15 @@ void EAGLE_PLUGIN::packageWire( FOOTPRINT* aFootprint, wxXmlNode* aTree ) const
             // line widths.
             switch( layer )
             {
-            case Edge_Cuts: width = Millimeter2iu( DEFAULT_EDGE_WIDTH );      break;
+            case Edge_Cuts: width = pcbIUScale.mmToIU( DEFAULT_EDGE_WIDTH );      break;
 
             case F_SilkS:
-            case B_SilkS:   width = Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ); break;
+            case B_SilkS:   width = pcbIUScale.mmToIU( DEFAULT_SILK_LINE_WIDTH ); break;
 
             case F_CrtYd:
-            case B_CrtYd:   width = Millimeter2iu( DEFAULT_COURTYARD_WIDTH ); break;
+            case B_CrtYd:   width = pcbIUScale.mmToIU( DEFAULT_COURTYARD_WIDTH ); break;
 
-            default:        width = Millimeter2iu( DEFAULT_LINE_WIDTH );      break;
+            default:        width = pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH );      break;
             }
         }
     }
diff --git a/pcbnew/plugins/kicad/pcb_parser.cpp b/pcbnew/plugins/kicad/pcb_parser.cpp
index 2a403e1746..91e5e3db0a 100644
--- a/pcbnew/plugins/kicad/pcb_parser.cpp
+++ b/pcbnew/plugins/kicad/pcb_parser.cpp
@@ -2828,7 +2828,7 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE()
     // external tools can generate invalid files.
     if( stroke.GetWidth() <= 0 && !shape->IsFilled() )
     {
-        stroke.SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) );
+        stroke.SetWidth( pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ) );
     }
 
     shape->SetStroke( stroke );
@@ -4551,7 +4551,7 @@ FP_SHAPE* PCB_PARSER::parseFP_SHAPE()
     // external tools can generate invalid files.
     if( stroke.GetWidth() <= 0 && !shape->IsFilled() )
     {
-        stroke.SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) );
+        stroke.SetWidth( pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ) );
     }
 
     shape->SetStroke( stroke );
diff --git a/pcbnew/plugins/pcad/pcad2kicad_common.cpp b/pcbnew/plugins/pcad/pcad2kicad_common.cpp
index 38491e1432..20bad99ee7 100644
--- a/pcbnew/plugins/pcad/pcad2kicad_common.cpp
+++ b/pcbnew/plugins/pcad/pcad2kicad_common.cpp
@@ -156,7 +156,7 @@ double StrToDoublePrecisionUnits( const wxString& aStr, char aAxe,
                 i = i * (0.0254 / 0.025);
 #endif
 
-            i = Millimeter2iu( i );
+            i = pcbIUScale.mmToIU( i );
         }
         else
         {
diff --git a/pcbnew/plugins/pcad/pcb_pad.cpp b/pcbnew/plugins/pcad/pcb_pad.cpp
index c3aaa2758e..3311a1772a 100644
--- a/pcbnew/plugins/pcad/pcb_pad.cpp
+++ b/pcbnew/plugins/pcad/pcb_pad.cpp
@@ -219,7 +219,7 @@ void PCB_PAD::AddToFootprint( FOOTPRINT* aFootprint, const EDA_ANGLE& aRotation,
         {
             int sm_margin = ( m_Shapes[0]->m_Width - m_Hole ) / 2;
             pad->SetLocalSolderMaskMargin( sm_margin );
-            pad->SetLocalClearance( sm_margin + Millimeter2iu( 0.254 ) );
+            pad->SetLocalClearance( sm_margin + pcbIUScale.mmToIU( 0.254 ) );
         }
 
         pad->SetLayerSet( LSET::AllCuMask() | LSET( 2, B_Mask, F_Mask ) );
diff --git a/pcbnew/teardrop/teardrop.cpp b/pcbnew/teardrop/teardrop.cpp
index 708048b433..cccd81441b 100644
--- a/pcbnew/teardrop/teardrop.cpp
+++ b/pcbnew/teardrop/teardrop.cpp
@@ -70,7 +70,7 @@ ZONE* TEARDROP_MANAGER::createTeardrop( TEARDROP_VARIANT aTeardropVariant,
     teardrop->SetLayer( aTrack->GetLayer() );
     teardrop->SetNetCode( aTrack->GetNetCode() );
     teardrop->SetLocalClearance( 0 );
-    teardrop->SetMinThickness( Millimeter2iu( 0.0254 ) );  // The minimum zone thickness
+    teardrop->SetMinThickness( pcbIUScale.mmToIU( 0.0254 ) );  // The minimum zone thickness
     teardrop->SetPadConnection( ZONE_CONNECTION::FULL );
     teardrop->SetIsFilled( false );
     teardrop->SetZoneName( aTeardropVariant == TD_TYPE_PADVIA ?
@@ -93,7 +93,7 @@ ZONE* TEARDROP_MANAGER::createTeardrop( TEARDROP_VARIANT aTeardropVariant,
 int TEARDROP_MANAGER::SetTeardrops( BOARD_COMMIT* aCommitter, bool aFollowTracks )
 {
     // Init parameters:
-    m_tolerance = Millimeter2iu( 0.01 );
+    m_tolerance = pcbIUScale.mmToIU( 0.01 );
 
     int count = 0;      // Number of created teardrop
 
@@ -204,12 +204,12 @@ int TEARDROP_MANAGER::SetTeardrops( BOARD_COMMIT* aCommitter, bool aFollowTracks
     // Exact shapes can be calculated only on a full zone refill, **much more** time consuming
     if( m_createdTdList.size() )
     {
-        int epsilon = Millimeter2iu( 0.001 );
+        int epsilon = pcbIUScale.mmToIU( 0.001 );
 
         for( ZONE* zone: m_createdTdList )
         {
             int half_min_width = zone->GetMinThickness() / 2;
-            int numSegs = GetArcToSegmentCount( half_min_width, Millimeter2iu( 0.005 ), FULL_CIRCLE );
+            int numSegs = GetArcToSegmentCount( half_min_width, pcbIUScale.mmToIU( 0.005 ), FULL_CIRCLE );
             SHAPE_POLY_SET filledPolys = *zone->Outline();
 
             filledPolys.Deflate( half_min_width - epsilon, numSegs );
diff --git a/pcbnew/teardrop/teardrop_parameters.h b/pcbnew/teardrop/teardrop_parameters.h
index b8fe73dc16..b8d53f76c1 100644
--- a/pcbnew/teardrop/teardrop_parameters.h
+++ b/pcbnew/teardrop/teardrop_parameters.h
@@ -49,8 +49,8 @@ class TEARDROP_PARAMETERS
 public:
     TEARDROP_PARAMETERS( TARGET_TD aTdType ):
         m_TdType( aTdType ),
-        m_TdMaxLen( Millimeter2iu( 1.0 ) ),
-        m_TdMaxHeight( Millimeter2iu( 2.0 ) ),
+        m_TdMaxLen( pcbIUScale.mmToIU( 1.0 ) ),
+        m_TdMaxHeight( pcbIUScale.mmToIU( 2.0 ) ),
         m_LengthRatio( 0.5),
         m_HeightRatio( 1.0 ),
         m_CurveSegCount( 0 ),
diff --git a/pcbnew/teardrop/teardrop_utils.cpp b/pcbnew/teardrop/teardrop_utils.cpp
index b36a48cb73..8545e1b0a7 100644
--- a/pcbnew/teardrop/teardrop_utils.cpp
+++ b/pcbnew/teardrop/teardrop_utils.cpp
@@ -721,7 +721,7 @@ bool TEARDROP_MANAGER::computeTeardropPolygonPoints( TEARDROP_PARAMETERS* aCurrP
     VECTOR2I pointD = aViaPad.m_Pos;
     // add a small offset in order to have the aViaPad.m_Pos reference point inside
     // the teardrop area, just in case...
-    int offset = Millimeter2iu( 0.001 );
+    int offset = pcbIUScale.mmToIU( 0.001 );
     pointD += VECTOR2I( int( -vecT.x*offset), int(-vecT.y*offset) );
 
     VECTOR2I pointC, pointE;     // Point on PADVIA outlines
diff --git a/pcbnew/tools/drawing_stackup_table_tool.cpp b/pcbnew/tools/drawing_stackup_table_tool.cpp
index 47e7a29605..ab9b934c06 100644
--- a/pcbnew/tools/drawing_stackup_table_tool.cpp
+++ b/pcbnew/tools/drawing_stackup_table_tool.cpp
@@ -78,8 +78,8 @@ static std::vector<BOARD_ITEM*> initTextTable( std::vector<std::vector<PCB_TEXT*
     //  +--------------------------------+
     //
 
-    int xmargin = Millimeter2iu( 0.75 );
-    int ymargin = Millimeter2iu( 0.75 );
+    int xmargin = pcbIUScale.mmToIU( 0.75 );
+    int ymargin = pcbIUScale.mmToIU( 0.75 );
 
     // Init table
     for( i = 0; i < nbRows; i++ )
@@ -206,8 +206,8 @@ std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawSpecificationStackup( const VECTOR2I&
     // Style : Header
     std::unique_ptr<PCB_TEXT> headStyle = std::make_unique<PCB_TEXT>( footprint );
     headStyle->SetLayer( Eco1_User );
-    headStyle->SetTextSize( wxSize( Millimeter2iu( 1.5 ), Millimeter2iu( 1.5 ) ) );
-    headStyle->SetTextThickness( Millimeter2iu( 0.3 ) );
+    headStyle->SetTextSize( wxSize( pcbIUScale.mmToIU( 1.5 ), pcbIUScale.mmToIU( 1.5 ) ) );
+    headStyle->SetTextThickness( pcbIUScale.mmToIU( 0.3 ) );
     headStyle->SetItalic( false );
     headStyle->SetTextPos( wxPoint( 0, 0 ) );
     headStyle->SetText( _( "Layer" ) );
@@ -217,8 +217,8 @@ std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawSpecificationStackup( const VECTOR2I&
     // Style : data
     std::unique_ptr<PCB_TEXT> dataStyle = std::make_unique<PCB_TEXT>( footprint );
     dataStyle->SetLayer( Eco1_User );
-    dataStyle->SetTextSize( wxSize( Millimeter2iu( 1.5 ), Millimeter2iu( 1.5 ) ) );
-    dataStyle->SetTextThickness( Millimeter2iu( 0.1 ) );
+    dataStyle->SetTextSize( wxSize( pcbIUScale.mmToIU( 1.5 ), pcbIUScale.mmToIU( 1.5 ) ) );
+    dataStyle->SetTextThickness( pcbIUScale.mmToIU( 0.1 ) );
     dataStyle->SetItalic( false );
     dataStyle->SetTextPos( wxPoint( 0, 0 ) );
     dataStyle->SetText( _( "Layer" ) );
@@ -374,8 +374,8 @@ std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawBoardCharacteristics( const VECTOR2I&
     std::unique_ptr<PCB_TEXT> headStyle =
             std::make_unique<PCB_TEXT>( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
     headStyle->SetLayer( Eco1_User );
-    headStyle->SetTextSize( wxSize( Millimeter2iu( 2.0 ), Millimeter2iu( 2.0 ) ) );
-    headStyle->SetTextThickness( Millimeter2iu( 0.4 ) );
+    headStyle->SetTextSize( wxSize( pcbIUScale.mmToIU( 2.0 ), pcbIUScale.mmToIU( 2.0 ) ) );
+    headStyle->SetTextThickness( pcbIUScale.mmToIU( 0.4 ) );
     headStyle->SetItalic( false );
     headStyle->SetTextPos( wxPoint( 0, 0 ) );
     headStyle->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
@@ -385,8 +385,8 @@ std::vector<BOARD_ITEM*> DRAWING_TOOL::DrawBoardCharacteristics( const VECTOR2I&
     std::unique_ptr<PCB_TEXT> dataStyle =
             std::make_unique<PCB_TEXT>( static_cast<FOOTPRINT*>( m_frame->GetModel() ) );
     dataStyle->SetLayer( Eco1_User );
-    dataStyle->SetTextSize( wxSize( Millimeter2iu( 1.5 ), Millimeter2iu( 1.5 ) ) );
-    dataStyle->SetTextThickness( Millimeter2iu( 0.2 ) );
+    dataStyle->SetTextSize( wxSize( pcbIUScale.mmToIU( 1.5 ), pcbIUScale.mmToIU( 1.5 ) ) );
+    dataStyle->SetTextThickness( pcbIUScale.mmToIU( 0.2 ) );
     dataStyle->SetItalic( false );
     dataStyle->SetTextPos( wxPoint( 0, 0 ) );
     dataStyle->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp
index 46a607b5f5..3a080ff4fa 100644
--- a/pcbnew/tools/drawing_tool.cpp
+++ b/pcbnew/tools/drawing_tool.cpp
@@ -73,7 +73,7 @@
 #include <string_utils.h>
 #include <zone.h>
 
-const unsigned int DRAWING_TOOL::COORDS_PADDING = Millimeter2iu( 20 );
+const unsigned int DRAWING_TOOL::COORDS_PADDING = pcbIUScale.mmToIU( 20 );
 
 using SCOPED_DRAW_MODE = SCOPED_SET_RESET<DRAWING_TOOL::MODE>;
 
@@ -3230,7 +3230,7 @@ int DRAWING_TOOL::getSegmentWidth( PCB_LAYER_ID aLayer ) const
 }
 
 
-const unsigned int DRAWING_TOOL::WIDTH_STEP = Millimeter2iu( 0.1 );
+const unsigned int DRAWING_TOOL::WIDTH_STEP = pcbIUScale.mmToIU( 0.1 );
 
 
 void DRAWING_TOOL::setTransitions()
diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp
index c024a8f17c..33312c7fea 100644
--- a/pcbnew/tools/edit_tool.cpp
+++ b/pcbnew/tools/edit_tool.cpp
@@ -65,7 +65,7 @@ using namespace std::placeholders;
 #include <pcb_target.h>
 #include <zone_filler.h>
 
-const unsigned int EDIT_TOOL::COORDS_PADDING = Millimeter2iu( 20 );
+const unsigned int EDIT_TOOL::COORDS_PADDING = pcbIUScale.mmToIU( 20 );
 
 EDIT_TOOL::EDIT_TOOL() :
         PCB_TOOL_BASE( "pcbnew.InteractiveEdit" ),
diff --git a/pcbnew/tools/pcb_point_editor.cpp b/pcbnew/tools/pcb_point_editor.cpp
index 0fabe38e52..a99e1722a9 100644
--- a/pcbnew/tools/pcb_point_editor.cpp
+++ b/pcbnew/tools/pcb_point_editor.cpp
@@ -50,7 +50,7 @@ using namespace std::placeholders;
 #include <connectivity/connectivity_data.h>
 #include <progress_reporter.h>
 
-const unsigned int PCB_POINT_EDITOR::COORDS_PADDING = Millimeter2iu( 20 );
+const unsigned int PCB_POINT_EDITOR::COORDS_PADDING = pcbIUScale.mmToIU( 20 );
 
 // Few constants to avoid using bare numbers for point indices
 enum SEG_POINTS
diff --git a/pcbnew/tools/pcb_selection_tool.cpp b/pcbnew/tools/pcb_selection_tool.cpp
index a3036fcc17..199f856d23 100644
--- a/pcbnew/tools/pcb_selection_tool.cpp
+++ b/pcbnew/tools/pcb_selection_tool.cpp
@@ -1687,7 +1687,7 @@ void PCB_SELECTION_TOOL::ZoomFitCrossProbeBBox( const BOX2I& aBBox )
     // This ratio is not useful by itself as a scaling factor.  It must be "bent" to
     // provide good scaling at varying component sizes.  Bigger components need less
     // scaling than small ones.
-    double currTextHeight = Millimeter2iu( DEFAULT_TEXT_SIZE );
+    double currTextHeight = pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE );
 
     double compRatio = bbSize.y / currTextHeight; // Ratio of component to text height
 
diff --git a/pcbnew/zone.cpp b/pcbnew/zone.cpp
index 63c6efb430..0931db38dc 100644
--- a/pcbnew/zone.cpp
+++ b/pcbnew/zone.cpp
@@ -373,7 +373,7 @@ bool ZONE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
 {
     // When looking for an "exact" hit aAccuracy will be 0 which works poorly for very thin
     // lines.  Give it a floor.
-    int accuracy = std::max( aAccuracy, Millimeter2iu( 0.1 ) );
+    int accuracy = std::max( aAccuracy, pcbIUScale.mmToIU( 0.1 ) );
 
     return HitTestForCorner( aPosition, accuracy * 2 ) || HitTestForEdge( aPosition, accuracy );
 }
@@ -772,9 +772,9 @@ void ZONE::SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE aBorderHatchStyle,
                                   bool aRebuildBorderHatch )
 {
     aBorderHatchPitch = std::max( aBorderHatchPitch,
-                                  Millimeter2iu( ZONE_BORDER_HATCH_MINDIST_MM ) );
+                                  pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MINDIST_MM ) );
     aBorderHatchPitch = std::min( aBorderHatchPitch,
-                                  Millimeter2iu( ZONE_BORDER_HATCH_MAXDIST_MM ) );
+                                  pcbIUScale.mmToIU( ZONE_BORDER_HATCH_MAXDIST_MM ) );
     SetBorderHatchPitch( aBorderHatchPitch );
     m_borderStyle = aBorderHatchStyle;
 
@@ -986,7 +986,7 @@ bool ZONE::IsIsland( PCB_LAYER_ID aLayer, int aPolyIdx ) const
 
 void ZONE::GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aZones ) const
 {
-    int   epsilon = Millimeter2iu( 0.001 );
+    int   epsilon = pcbIUScale.mmToIU( 0.001 );
     BOX2I bbox = GetCachedBoundingBox();
 
     bbox.Inflate( epsilon );
diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp
index 3f7632ec2d..b0ff5aa677 100644
--- a/pcbnew/zone_filler.cpp
+++ b/pcbnew/zone_filler.cpp
@@ -681,7 +681,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
     // requested clearance due to many approximations in calculations, like arc to segment
     // approx, rounding issues, etc.
     BOX2I zone_boundingbox = aZone->GetCachedBoundingBox();
-    int   extra_margin = Millimeter2iu( ADVANCED_CFG::GetCfg().m_ExtraClearance );
+    int   extra_margin = pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_ExtraClearance );
 
     // Items outside the zone bounding box are skipped, so it needs to be inflated by the
     // largest clearance value found in the netclasses and rules
@@ -1047,7 +1047,7 @@ bool ZONE_FILLER::fillCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer, PCB_LA
     // min_width should not.  Therefore we subtract epsilon from the min_width when
     // deflating/inflating.
     int half_min_width = aZone->GetMinThickness() / 2;
-    int epsilon = Millimeter2iu( 0.001 );
+    int epsilon = pcbIUScale.mmToIU( 0.001 );
     int numSegs = GetArcToSegmentCount( half_min_width, m_maxError, FULL_CIRCLE );
 
     // Solid polygons are deflated and inflated during calculations.  Deflating doesn't cause
@@ -1297,7 +1297,7 @@ bool ZONE_FILLER::fillNonCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer,
     // min_width should not.  Therefore we subtract epsilon from the min_width when
     // deflating/inflating.
     int half_min_width = aZone->GetMinThickness() / 2;
-    int epsilon = Millimeter2iu( 0.001 );
+    int epsilon = pcbIUScale.mmToIU( 0.001 );
     int numSegs = GetArcToSegmentCount( half_min_width, m_maxError, FULL_CIRCLE );
 
     aFillPolys.Deflate( half_min_width - epsilon, numSegs );
@@ -1491,7 +1491,7 @@ bool ZONE_FILLER::addHatchFillTypeOnZone( const ZONE* aZone, PCB_LAYER_ID aLayer
     // This margin also avoid problems due to rounding coordinates in next calculations
     // that can create incorrect polygons
     int thickness = std::max( aZone->GetHatchThickness(),
-                              aZone->GetMinThickness() + Millimeter2iu( 0.001 ) );
+                              aZone->GetMinThickness() + pcbIUScale.mmToIU( 0.001 ) );
 
     int linethickness = thickness - aZone->GetMinThickness();
     int gridsize = thickness + aZone->GetHatchGap();
@@ -1539,13 +1539,13 @@ bool ZONE_FILLER::addHatchFillTypeOnZone( const ZONE* aZone, PCB_LAYER_ID aLayer
         #define SMOOTH_MIN_VAL_MM 0.02
         #define SMOOTH_SMALL_VAL_MM 0.04
 
-        if( smooth_value > Millimeter2iu( SMOOTH_MIN_VAL_MM ) )
+        if( smooth_value > pcbIUScale.mmToIU( SMOOTH_MIN_VAL_MM ) )
         {
             SHAPE_POLY_SET smooth_hole;
             smooth_hole.AddOutline( hole_base );
             int smooth_level = aZone->GetHatchSmoothingLevel();
 
-            if( smooth_value < Millimeter2iu( SMOOTH_SMALL_VAL_MM ) && smooth_level > 1 )
+            if( smooth_value < pcbIUScale.mmToIU( SMOOTH_SMALL_VAL_MM ) && smooth_level > 1 )
                 smooth_level = 1;
 
             // Use a larger smooth_value to compensate the outline tickness
@@ -1556,7 +1556,7 @@ bool ZONE_FILLER::addHatchFillTypeOnZone( const ZONE* aZone, PCB_LAYER_ID aLayer
             smooth_value = std::min( smooth_value, aZone->GetHatchGap() / 2 );
 
             // the error to approximate a circle by segments when smoothing corners by a arc
-            int error_max = std::max( Millimeter2iu( 0.01 ), smooth_value / 20 );
+            int error_max = std::max( pcbIUScale.mmToIU( 0.01 ), smooth_value / 20 );
 
             switch( smooth_level )
             {
diff --git a/qa/unittests/eeschema/test_sch_biu.cpp b/qa/unittests/eeschema/test_sch_biu.cpp
index 7be1563173..6558a8e930 100644
--- a/qa/unittests/eeschema/test_sch_biu.cpp
+++ b/qa/unittests/eeschema/test_sch_biu.cpp
@@ -49,13 +49,13 @@ BOOST_FIXTURE_TEST_SUITE( SchInternalUnits, TEST_SCH_INTERNAL_UNITS )
 
 BOOST_AUTO_TEST_CASE( ConvertToInternalUnits )
 {
-    BOOST_CHECK_EQUAL( Millimeter2iu( 1.0 ), 10000 );
+    BOOST_CHECK_EQUAL( schIUScale.mmToIU( 1.0 ), 10000 );
 }
 
 
 BOOST_AUTO_TEST_CASE( ConvertFromInternalUnits )
 {
-    BOOST_CHECK_EQUAL( static_cast< int >( Iu2Millimeter( 10000 ) ), 1 );
+    BOOST_CHECK_EQUAL( static_cast< int >( schIUScale.IUTomm( 10000 ) ), 1 );
 }
 
 
diff --git a/qa/unittests/libs/kimath/geometry/test_shape_arc.cpp b/qa/unittests/libs/kimath/geometry/test_shape_arc.cpp
index a305e87a0e..70cf0d76a3 100644
--- a/qa/unittests/libs/kimath/geometry/test_shape_arc.cpp
+++ b/qa/unittests/libs/kimath/geometry/test_shape_arc.cpp
@@ -719,9 +719,9 @@ struct ARC_DATA_MM
 
     SHAPE_ARC GenerateArc() const
     {
-        SHAPE_ARC arc( VECTOR2D( PcbMm2iu( m_center_x ), PcbMm2iu( m_center_y ) ),
-                       VECTOR2D( PcbMm2iu( m_start_x ), PcbMm2iu( m_start_y ) ),
-                       EDA_ANGLE( m_center_angle, DEGREES_T ), PcbMm2iu( m_width ) );
+        SHAPE_ARC arc( VECTOR2D( pcbIUScale.mmToIU( m_center_x ), pcbIUScale.mmToIU( m_center_y ) ),
+                       VECTOR2D( pcbIUScale.mmToIU( m_start_x ), pcbIUScale.mmToIU( m_start_y ) ),
+                       EDA_ANGLE( m_center_angle, DEGREES_T ), pcbIUScale.mmToIU( m_width ) );
 
         return arc;
     }
@@ -836,17 +836,17 @@ BOOST_AUTO_TEST_CASE( CollideArc )
             SHAPE* arc1_slc_sh = &arc1_slc;
             SHAPE* arc2_slc_sh = &arc2_slc;
 
-            bool result_arc_to_arc =
-                    arc1_sh->Collide( arc2_sh, PcbMm2iu( c.m_clearance ), &actual, &location );
+            bool result_arc_to_arc = arc1_sh->Collide( arc2_sh, pcbIUScale.mmToIU( c.m_clearance ),
+                                                       &actual, &location );
 
             // For arc to chain collisions, we need to re-calculate the clearances because the
             // SHAPE_LINE_CHAIN is zero width
-            int clearance = PcbMm2iu( c.m_clearance ) + ( arc2.GetWidth() / 2 );
+            int clearance = pcbIUScale.mmToIU( c.m_clearance ) + ( arc2.GetWidth() / 2 );
 
             bool result_arc_to_chain =
                     arc1_sh->Collide( arc2_slc_sh, clearance, &actual, &location );
 
-            clearance = PcbMm2iu( c.m_clearance ) + ( arc1.GetWidth() / 2 );
+            clearance = pcbIUScale.mmToIU( c.m_clearance ) + ( arc1.GetWidth() / 2 );
             bool result_chain_to_arc =
                     arc1_slc_sh->Collide( arc2_sh, clearance, &actual, &location );