From 7214a108e464c0b16b4ec94921ba05eb52b3e1f3 Mon Sep 17 00:00:00 2001
From: John Beard <john.j.beard@gmail.com>
Date: Tue, 8 Oct 2024 08:42:04 +0800
Subject: [PATCH] Text alignment: add a flip function

Reduces the need for client code to know it can exploit the
enum -1/+1 properties. ToHAlignment provides an explicit
contract for integral conversion, and also doesn't rely on the
int being exactly -1, 0 or 1 (failure to adhere to which would
be UB).
---
 eeschema/autoplace_fields.cpp              |  7 +--
 eeschema/tools/sch_edit_tool.cpp           |  8 +--
 eeschema/tools/symbol_editor_edit_tool.cpp |  4 +-
 include/font/text_attributes.h             | 60 +++++++++++++++++++++-
 4 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/eeschema/autoplace_fields.cpp b/eeschema/autoplace_fields.cpp
index 5f2febb442..f800801a53 100644
--- a/eeschema/autoplace_fields.cpp
+++ b/eeschema/autoplace_fields.cpp
@@ -519,9 +519,10 @@ protected:
     void justifyField( SCH_FIELD* aField, SIDE aFieldSide )
     {
         // Justification is set twice to allow IsHorizJustifyFlipped() to work correctly.
-        aField->SetHorizJustify( TO_HJUSTIFY( -aFieldSide.x ) );
-        aField->SetHorizJustify( TO_HJUSTIFY( -aFieldSide.x
-                                                 * ( aField->IsHorizJustifyFlipped() ? -1 : 1 ) ) );
+        aField->SetHorizJustify( ToHAlignment( -aFieldSide.x ) );
+        if( aField->IsHorizJustifyFlipped() )
+            aField->SetHorizJustify( GetFlippedAlignment( aField->GetHorizJustify() ) );
+
         aField->SetVertJustify( GR_TEXT_V_ALIGN_CENTER );
     }
 
diff --git a/eeschema/tools/sch_edit_tool.cpp b/eeschema/tools/sch_edit_tool.cpp
index fb1b2b6b0e..8f188e333c 100644
--- a/eeschema/tools/sch_edit_tool.cpp
+++ b/eeschema/tools/sch_edit_tool.cpp
@@ -1037,9 +1037,9 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
             SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
 
             if( vertical )
-                field->SetVertJustify( TO_VJUSTIFY( -field->GetVertJustify() ) );
+                field->SetVertJustify( GetFlippedAlignment( field->GetVertJustify() ) );
             else
-                field->SetHorizJustify( TO_HJUSTIFY( -field->GetHorizJustify() ) );
+                field->SetHorizJustify( GetFlippedAlignment( field->GetHorizJustify() ) );
 
             // Now that we're re-justifying a field, they're no longer autoplaced.
             static_cast<SCH_ITEM*>( field->GetParent() )->ClearFieldsAutoplaced();
@@ -1116,9 +1116,9 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
                 SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
 
                 if( vertical )
-                    field->SetVertJustify( TO_VJUSTIFY( -field->GetVertJustify() ) );
+                    field->SetVertJustify( GetFlippedAlignment( field->GetVertJustify() ) );
                 else
-                    field->SetHorizJustify( TO_HJUSTIFY( -field->GetHorizJustify() ) );
+                    field->SetHorizJustify( GetFlippedAlignment( field->GetHorizJustify() ) );
 
                 // Now that we're re-justifying a field, they're no longer autoplaced.
                 static_cast<SCH_ITEM*>( field->GetParent() )->ClearFieldsAutoplaced();
diff --git a/eeschema/tools/symbol_editor_edit_tool.cpp b/eeschema/tools/symbol_editor_edit_tool.cpp
index 91d811beb2..46de7b065f 100644
--- a/eeschema/tools/symbol_editor_edit_tool.cpp
+++ b/eeschema/tools/symbol_editor_edit_tool.cpp
@@ -221,9 +221,9 @@ int SYMBOL_EDITOR_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
             SCH_FIELD* field = static_cast<SCH_FIELD*>( item );
 
             if( xAxis )
-                field->SetVertJustify( TO_VJUSTIFY( -field->GetVertJustify() ) );
+                field->SetVertJustify( GetFlippedAlignment( field->GetVertJustify() ) );
             else
-                field->SetHorizJustify( TO_HJUSTIFY( -field->GetHorizJustify() ) );
+                field->SetHorizJustify( GetFlippedAlignment( field->GetHorizJustify() ) );
 
             break;
         }
diff --git a/include/font/text_attributes.h b/include/font/text_attributes.h
index 34b8bef2f6..e1ac7640fc 100644
--- a/include/font/text_attributes.h
+++ b/include/font/text_attributes.h
@@ -57,8 +57,64 @@ enum GR_TEXT_V_ALIGN_T
 };
 
 
-#define TO_HJUSTIFY( x ) static_cast<GR_TEXT_H_ALIGN_T>( x )
-#define TO_VJUSTIFY( x ) static_cast<GR_TEXT_V_ALIGN_T>( x )
+/**
+ * Get the reverse alignment: left-right are swapped,
+ * others are unchanged.
+ */
+constexpr GR_TEXT_H_ALIGN_T GetFlippedAlignment( GR_TEXT_H_ALIGN_T aAlign )
+{
+    // Could use the -1/1 promise of the enum too.
+    switch( aAlign )
+    {
+    case GR_TEXT_H_ALIGN_LEFT:
+        return GR_TEXT_H_ALIGN_RIGHT;
+    case GR_TEXT_H_ALIGN_RIGHT:
+        return GR_TEXT_H_ALIGN_LEFT;
+    case GR_TEXT_H_ALIGN_CENTER:
+    case GR_TEXT_H_ALIGN_INDETERMINATE:
+        break;
+    }
+    return aAlign;
+};
+
+
+/**
+ * Get the reverse alignment: top-bottom are swapped,
+ * others are unchanged.
+ */
+constexpr GR_TEXT_V_ALIGN_T GetFlippedAlignment( GR_TEXT_V_ALIGN_T aAlign )
+{
+    switch( aAlign )
+    {
+    case GR_TEXT_V_ALIGN_BOTTOM:
+        return GR_TEXT_V_ALIGN_TOP;
+    case GR_TEXT_V_ALIGN_TOP:
+        return GR_TEXT_V_ALIGN_BOTTOM;
+    case GR_TEXT_V_ALIGN_CENTER:
+    case GR_TEXT_V_ALIGN_INDETERMINATE:
+        break;
+    }
+    return aAlign;
+};
+
+
+/**
+ * Convert an integral value to horizontal alignment.
+ *
+ *  * x < 0: Left align
+ *  * x == 0: Center
+ *  * x > 0: Right align
+ */
+constexpr GR_TEXT_H_ALIGN_T ToHAlignment( int x )
+{
+    if( x < 0 )
+
+        return GR_TEXT_H_ALIGN_LEFT;
+    else if( x > 0 )
+        return GR_TEXT_H_ALIGN_RIGHT;
+
+    return GR_TEXT_H_ALIGN_CENTER;
+}
 
 
 class GAL_API TEXT_ATTRIBUTES